am 42bc734b
: Merge "Block access to accounts for limited users." into jb-mr2-dev
* commit '42bc734b302f1fe68c031e013513535bed4c24f1': Block access to accounts for limited users.
This commit is contained in:
@ -16984,6 +16984,7 @@ package android.os {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class UserManager {
|
public class UserManager {
|
||||||
|
method public static synchronized android.os.UserManager get(android.content.Context);
|
||||||
method public long getSerialNumberForUser(android.os.UserHandle);
|
method public long getSerialNumberForUser(android.os.UserHandle);
|
||||||
method public int getUserCount();
|
method public int getUserCount();
|
||||||
method public android.os.UserHandle getUserForSerialNumber(long);
|
method public android.os.UserHandle getUserForSerialNumber(long);
|
||||||
|
@ -387,6 +387,23 @@ public class AccountManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
* For use by internal activities. Returns the list of accounts that the calling package
|
||||||
|
* is authorized to use, particularly for shared accounts.
|
||||||
|
* @param packageName package name of the calling app.
|
||||||
|
* @param uid the uid of the calling app.
|
||||||
|
* @return the accounts that are available to this package and user.
|
||||||
|
*/
|
||||||
|
public Account[] getAccountsForPackage(String packageName, int uid) {
|
||||||
|
try {
|
||||||
|
return mService.getAccountsForPackage(packageName, uid);
|
||||||
|
} catch (RemoteException re) {
|
||||||
|
// possible security exception
|
||||||
|
throw new RuntimeException(re);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists all accounts of a particular type. The account type is a
|
* Lists all accounts of a particular type. The account type is a
|
||||||
* string token corresponding to the authenticator and useful domain
|
* string token corresponding to the authenticator and useful domain
|
||||||
@ -575,7 +592,7 @@ public class AccountManager {
|
|||||||
public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
|
public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
try {
|
try {
|
||||||
return mService.addAccount(account, password, userdata);
|
return mService.addAccountExplicitly(account, password, userdata);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// won't ever happen
|
// won't ever happen
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@ -1123,7 +1140,7 @@ public class AccountManager {
|
|||||||
|
|
||||||
return new AmsTask(activity, handler, callback) {
|
return new AmsTask(activity, handler, callback) {
|
||||||
public void doWork() throws RemoteException {
|
public void doWork() throws RemoteException {
|
||||||
mService.addAcount(mResponse, accountType, authTokenType,
|
mService.addAccount(mResponse, accountType, authTokenType,
|
||||||
requiredFeatures, activity != null, optionsIn);
|
requiredFeatures, activity != null, optionsIn);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
|
@ -18,9 +18,14 @@ package android.accounts;
|
|||||||
import com.google.android.collect.Sets;
|
import com.google.android.collect.Sets;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManagerNative;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -29,6 +34,7 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
|
|
||||||
@ -119,6 +125,9 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
private Parcelable[] mExistingAccounts = null;
|
private Parcelable[] mExistingAccounts = null;
|
||||||
private int mSelectedItemIndex;
|
private int mSelectedItemIndex;
|
||||||
private Button mOkButton;
|
private Button mOkButton;
|
||||||
|
private int mCallingUid;
|
||||||
|
private String mCallingPackage;
|
||||||
|
private boolean mDisallowAddAccounts;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -128,6 +137,24 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
+ savedInstanceState + ")");
|
+ savedInstanceState + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String message = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
IBinder activityToken = getActivityToken();
|
||||||
|
mCallingUid = ActivityManagerNative.getDefault().getLaunchedFromUid(activityToken);
|
||||||
|
mCallingPackage = ActivityManagerNative.getDefault().getLaunchedFromPackage(
|
||||||
|
activityToken);
|
||||||
|
if (mCallingUid != 0 && mCallingPackage != null) {
|
||||||
|
Bundle restrictions = UserManager.get(this)
|
||||||
|
.getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid)));
|
||||||
|
mDisallowAddAccounts =
|
||||||
|
restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false);
|
||||||
|
}
|
||||||
|
} catch (RemoteException re) {
|
||||||
|
// Couldn't figure out caller details
|
||||||
|
Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
|
||||||
|
}
|
||||||
|
|
||||||
// save some items we use frequently
|
// save some items we use frequently
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
|
|
||||||
@ -179,6 +206,11 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
// If there are no relevant accounts and only one relevant account type go directly to
|
// If there are no relevant accounts and only one relevant account type go directly to
|
||||||
// add account. Otherwise let the user choose.
|
// add account. Otherwise let the user choose.
|
||||||
if (mAccounts.isEmpty()) {
|
if (mAccounts.isEmpty()) {
|
||||||
|
if (mDisallowAddAccounts) {
|
||||||
|
setContentView(R.layout.app_not_authorized);
|
||||||
|
setTitle(R.string.error_message_title);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mSetOfRelevantAccountTypes.size() == 1) {
|
if (mSetOfRelevantAccountTypes.size() == 1) {
|
||||||
runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next());
|
runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next());
|
||||||
} else {
|
} else {
|
||||||
@ -296,7 +328,8 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (accountName == null || accountType == null) {
|
if (accountName == null || accountType == null) {
|
||||||
Account[] currentAccounts = AccountManager.get(this).getAccounts();
|
Account[] currentAccounts = AccountManager.get(this).getAccountsForPackage(
|
||||||
|
mCallingPackage, mCallingUid);
|
||||||
Set<Account> preExistingAccounts = new HashSet<Account>();
|
Set<Account> preExistingAccounts = new HashSet<Account>();
|
||||||
for (Parcelable accountParcel : mExistingAccounts) {
|
for (Parcelable accountParcel : mExistingAccounts) {
|
||||||
preExistingAccounts.add((Account) accountParcel);
|
preExistingAccounts.add((Account) accountParcel);
|
||||||
@ -347,7 +380,8 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
AccountManager.KEY_INTENT);
|
AccountManager.KEY_INTENT);
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
mPendingRequest = REQUEST_ADD_ACCOUNT;
|
mPendingRequest = REQUEST_ADD_ACCOUNT;
|
||||||
mExistingAccounts = AccountManager.get(this).getAccounts();
|
mExistingAccounts = AccountManager.get(this).getAccountsForPackage(mCallingPackage,
|
||||||
|
mCallingUid);
|
||||||
intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivityForResult(intent, REQUEST_ADD_ACCOUNT);
|
startActivityForResult(intent, REQUEST_ADD_ACCOUNT);
|
||||||
return;
|
return;
|
||||||
@ -424,12 +458,14 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
private String[] getListOfDisplayableOptions(ArrayList<Account> accounts) {
|
private String[] getListOfDisplayableOptions(ArrayList<Account> accounts) {
|
||||||
// List of options includes all accounts found together with "Add new account" as the
|
// List of options includes all accounts found together with "Add new account" as the
|
||||||
// last item in the list.
|
// last item in the list.
|
||||||
String[] listItems = new String[accounts.size() + 1];
|
String[] listItems = new String[accounts.size() + (mDisallowAddAccounts ? 0 : 1)];
|
||||||
for (int i = 0; i < accounts.size(); i++) {
|
for (int i = 0; i < accounts.size(); i++) {
|
||||||
listItems[i] = accounts.get(i).name;
|
listItems[i] = accounts.get(i).name;
|
||||||
}
|
}
|
||||||
|
if (!mDisallowAddAccounts) {
|
||||||
listItems[accounts.size()] = getResources().getString(
|
listItems[accounts.size()] = getResources().getString(
|
||||||
R.string.add_account_button_label);
|
R.string.add_account_button_label);
|
||||||
|
}
|
||||||
return listItems;
|
return listItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +475,8 @@ public class ChooseTypeAndAccountActivity extends Activity
|
|||||||
* allowable accounts, if provided.
|
* allowable accounts, if provided.
|
||||||
*/
|
*/
|
||||||
private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) {
|
private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) {
|
||||||
final Account[] accounts = accountManager.getAccounts();
|
final Account[] accounts = accountManager.getAccountsForPackage(mCallingPackage,
|
||||||
|
mCallingUid);
|
||||||
ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length);
|
ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length);
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
if (mSetOfAllowableAccounts != null
|
if (mSetOfAllowableAccounts != null
|
||||||
|
@ -31,10 +31,11 @@ interface IAccountManager {
|
|||||||
String getUserData(in Account account, String key);
|
String getUserData(in Account account, String key);
|
||||||
AuthenticatorDescription[] getAuthenticatorTypes();
|
AuthenticatorDescription[] getAuthenticatorTypes();
|
||||||
Account[] getAccounts(String accountType);
|
Account[] getAccounts(String accountType);
|
||||||
|
Account[] getAccountsForPackage(String packageName, int uid);
|
||||||
Account[] getAccountsAsUser(String accountType, int userId);
|
Account[] getAccountsAsUser(String accountType, int userId);
|
||||||
void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
|
void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
|
||||||
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
|
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
|
||||||
boolean addAccount(in Account account, String password, in Bundle extras);
|
boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
|
||||||
void removeAccount(in IAccountManagerResponse response, in Account account);
|
void removeAccount(in IAccountManagerResponse response, in Account account);
|
||||||
void invalidateAuthToken(String accountType, String authToken);
|
void invalidateAuthToken(String accountType, String authToken);
|
||||||
String peekAuthToken(in Account account, String authTokenType);
|
String peekAuthToken(in Account account, String authTokenType);
|
||||||
@ -47,7 +48,7 @@ interface IAccountManager {
|
|||||||
void getAuthToken(in IAccountManagerResponse response, in Account account,
|
void getAuthToken(in IAccountManagerResponse response, in Account account,
|
||||||
String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch,
|
String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch,
|
||||||
in Bundle options);
|
in Bundle options);
|
||||||
void addAcount(in IAccountManagerResponse response, String accountType,
|
void addAccount(in IAccountManagerResponse response, String accountType,
|
||||||
String authTokenType, in String[] requiredFeatures, boolean expectActivityLaunch,
|
String authTokenType, in String[] requiredFeatures, boolean expectActivityLaunch,
|
||||||
in Bundle options);
|
in Bundle options);
|
||||||
void updateCredentials(in IAccountManagerResponse response, in Account account,
|
void updateCredentials(in IAccountManagerResponse response, in Account account,
|
||||||
|
@ -121,6 +121,14 @@ public class UserManager {
|
|||||||
*/
|
*/
|
||||||
public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
|
public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
|
||||||
|
|
||||||
|
private static UserManager sInstance = null;
|
||||||
|
|
||||||
|
public synchronized static UserManager get(Context context) {
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public UserManager(Context context, IUserManager service) {
|
public UserManager(Context context, IUserManager service) {
|
||||||
|
56
core/res/res/layout/app_not_authorized.xml
Normal file
56
core/res/res/layout/app_not_authorized.xml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2013, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- Customizable description text -->
|
||||||
|
<TextView android:id="@+id/description"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:paddingTop="16dip"
|
||||||
|
android:paddingBottom="16dip"
|
||||||
|
android:paddingStart="16dip"
|
||||||
|
android:paddingEnd="16dip"
|
||||||
|
android:text="@string/app_no_restricted_accounts"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Horizontal divider line -->
|
||||||
|
<View android:layout_height="1dip"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:background="?android:attr/dividerHorizontal" />
|
||||||
|
|
||||||
|
<!-- Alert dialog style buttons along the bottom. -->
|
||||||
|
<LinearLayout android:id="@+id/button_bar"
|
||||||
|
style="?android:attr/buttonBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:measureWithLargestChild="true">
|
||||||
|
<Button android:id="@android:id/button1"
|
||||||
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
|
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@android:string/yes"
|
||||||
|
android:onClick="onCancelButtonClicked" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
@ -4063,5 +4063,10 @@
|
|||||||
<string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string>
|
<string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string>
|
||||||
<!-- Default name of the owner user [CHAR LIMIT=20] -->
|
<!-- Default name of the owner user [CHAR LIMIT=20] -->
|
||||||
<string name="owner_name" msgid="3879126011135546571">Owner</string>
|
<string name="owner_name" msgid="3879126011135546571">Owner</string>
|
||||||
|
<!-- Error message title [CHAR LIMIT=35] -->
|
||||||
|
<string name="error_message_title">Error</string>
|
||||||
|
<!-- Message informing user that app is not permitted to access accounts. [CHAR LIMIT=none] -->
|
||||||
|
<string name="app_no_restricted_accounts">This application does not support accounts for limited users</string>
|
||||||
|
<!-- Message informing user that the requested activity could not be found [CHAR LIMIT=none] -->
|
||||||
|
<string name="app_not_found">No application found to handle this action</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -869,7 +869,7 @@
|
|||||||
<java-symbol type="string" name="config_chooseAccountActivity" />
|
<java-symbol type="string" name="config_chooseAccountActivity" />
|
||||||
<java-symbol type="string" name="config_chooseTypeAndAccountActivity" />
|
<java-symbol type="string" name="config_chooseTypeAndAccountActivity" />
|
||||||
<java-symbol type="string" name="config_appsAuthorizedForSharedAccounts" />
|
<java-symbol type="string" name="config_appsAuthorizedForSharedAccounts" />
|
||||||
|
<java-symbol type="string" name="error_message_title" />
|
||||||
|
|
||||||
<java-symbol type="plurals" name="abbrev_in_num_days" />
|
<java-symbol type="plurals" name="abbrev_in_num_days" />
|
||||||
<java-symbol type="plurals" name="abbrev_in_num_hours" />
|
<java-symbol type="plurals" name="abbrev_in_num_hours" />
|
||||||
@ -1121,6 +1121,7 @@
|
|||||||
<java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
|
<java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
|
||||||
<java-symbol type="layout" name="keyguard_add_widget" />
|
<java-symbol type="layout" name="keyguard_add_widget" />
|
||||||
<java-symbol type="layout" name="action_bar_up_container" />
|
<java-symbol type="layout" name="action_bar_up_container" />
|
||||||
|
<java-symbol type="layout" name="app_not_authorized" />
|
||||||
|
|
||||||
<java-symbol type="anim" name="slide_in_child_bottom" />
|
<java-symbol type="anim" name="slide_in_child_bottom" />
|
||||||
<java-symbol type="anim" name="slide_in_right" />
|
<java-symbol type="anim" name="slide_in_right" />
|
||||||
|
@ -322,7 +322,7 @@ public class SettingsProvider extends ContentProvider {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
mBackupManager = new BackupManager(getContext());
|
mBackupManager = new BackupManager(getContext());
|
||||||
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
mUserManager = UserManager.get(getContext());
|
||||||
|
|
||||||
setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS);
|
setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS);
|
||||||
establishDbTracking(UserHandle.USER_OWNER);
|
establishDbTracking(UserHandle.USER_OWNER);
|
||||||
|
@ -206,8 +206,7 @@ class QuickSettings {
|
|||||||
mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
|
mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
|
||||||
@Override
|
@Override
|
||||||
protected Pair<String, Drawable> doInBackground(Void... params) {
|
protected Pair<String, Drawable> doInBackground(Void... params) {
|
||||||
final UserManager um =
|
final UserManager um = UserManager.get(mContext);
|
||||||
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
|
||||||
|
|
||||||
// Fall back to the UserManager nickname if we can't read the name from the local
|
// Fall back to the UserManager nickname if we can't read the name from the local
|
||||||
// profile below.
|
// profile below.
|
||||||
@ -292,8 +291,7 @@ class QuickSettings {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mBar.collapseAllPanels(true);
|
mBar.collapseAllPanels(true);
|
||||||
final UserManager um =
|
final UserManager um = UserManager.get(mContext);
|
||||||
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
|
||||||
if (um.getUsers(true).size() > 1) {
|
if (um.getUsers(true).size() > 1) {
|
||||||
try {
|
try {
|
||||||
WindowManagerGlobal.getWindowManagerService().lockNow(null);
|
WindowManagerGlobal.getWindowManagerService().lockNow(null);
|
||||||
|
@ -58,6 +58,7 @@ import android.os.HandlerThread;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@ -270,7 +271,7 @@ public class AccountManagerService
|
|||||||
|
|
||||||
private UserManager getUserManager() {
|
private UserManager getUserManager() {
|
||||||
if (mUserManager == null) {
|
if (mUserManager == null) {
|
||||||
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
mUserManager = UserManager.get(mContext);
|
||||||
}
|
}
|
||||||
return mUserManager;
|
return mUserManager;
|
||||||
}
|
}
|
||||||
@ -542,9 +543,9 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAccount(Account account, String password, Bundle extras) {
|
public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "addAccount: " + account
|
Log.v(TAG, "addAccountExplicitly: " + account
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + Binder.getCallingUid()
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
@ -1167,7 +1168,7 @@ public class AccountManagerService
|
|||||||
|
|
||||||
final int callingUid = getCallingUid();
|
final int callingUid = getCallingUid();
|
||||||
clearCallingIdentity();
|
clearCallingIdentity();
|
||||||
if (callingUid != android.os.Process.SYSTEM_UID) {
|
if (callingUid != Process.SYSTEM_UID) {
|
||||||
throw new SecurityException("can only call from system");
|
throw new SecurityException("can only call from system");
|
||||||
}
|
}
|
||||||
UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
|
UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
|
||||||
@ -1395,7 +1396,7 @@ public class AccountManagerService
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAcount(final IAccountManagerResponse response, final String accountType,
|
public void addAccount(final IAccountManagerResponse response, final String accountType,
|
||||||
final String authTokenType, final String[] requiredFeatures,
|
final String authTokenType, final String[] requiredFeatures,
|
||||||
final boolean expectActivityLaunch, final Bundle optionsIn) {
|
final boolean expectActivityLaunch, final Bundle optionsIn) {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
@ -1412,7 +1413,7 @@ public class AccountManagerService
|
|||||||
checkManageAccountsPermission();
|
checkManageAccountsPermission();
|
||||||
|
|
||||||
// Is user disallowed from modifying accounts?
|
// Is user disallowed from modifying accounts?
|
||||||
if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
|
if (!canUserModifyAccounts(Binder.getCallingUid())) {
|
||||||
try {
|
try {
|
||||||
response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
|
response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
|
||||||
"User is not allowed to add an account!");
|
"User is not allowed to add an account!");
|
||||||
@ -1457,7 +1458,7 @@ public class AccountManagerService
|
|||||||
int userId) {
|
int userId) {
|
||||||
// Only allow the system process to read accounts of other users
|
// Only allow the system process to read accounts of other users
|
||||||
if (userId != UserHandle.getCallingUserId()
|
if (userId != UserHandle.getCallingUserId()
|
||||||
&& Binder.getCallingUid() != android.os.Process.myUid()) {
|
&& Binder.getCallingUid() != Process.myUid()) {
|
||||||
throw new SecurityException("User " + UserHandle.getCallingUserId()
|
throw new SecurityException("User " + UserHandle.getCallingUserId()
|
||||||
+ " trying to confirm account credentials for " + userId);
|
+ " trying to confirm account credentials for " + userId);
|
||||||
}
|
}
|
||||||
@ -1573,7 +1574,8 @@ public class AccountManagerService
|
|||||||
|
|
||||||
public void run() throws RemoteException {
|
public void run() throws RemoteException {
|
||||||
synchronized (mAccounts.cacheLock) {
|
synchronized (mAccounts.cacheLock) {
|
||||||
mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid);
|
mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
// check whether each account matches the requested features
|
// check whether each account matches the requested features
|
||||||
mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length);
|
mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length);
|
||||||
@ -1662,7 +1664,7 @@ public class AccountManagerService
|
|||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
synchronized (accounts.cacheLock) {
|
synchronized (accounts.cacheLock) {
|
||||||
return getAccountsFromCacheLocked(accounts, null, callingUid);
|
return getAccountsFromCacheLocked(accounts, null, callingUid, null);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
restoreCallingIdentity(identityToken);
|
restoreCallingIdentity(identityToken);
|
||||||
@ -1703,7 +1705,7 @@ public class AccountManagerService
|
|||||||
if (userAccounts == null) continue;
|
if (userAccounts == null) continue;
|
||||||
synchronized (userAccounts.cacheLock) {
|
synchronized (userAccounts.cacheLock) {
|
||||||
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
|
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
|
||||||
Binder.getCallingUid());
|
Binder.getCallingUid(), null);
|
||||||
for (int a = 0; a < accounts.length; a++) {
|
for (int a = 0; a < accounts.length; a++) {
|
||||||
runningAccounts.add(new AccountAndUser(accounts[a], userId));
|
runningAccounts.add(new AccountAndUser(accounts[a], userId));
|
||||||
}
|
}
|
||||||
@ -1717,10 +1719,15 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Account[] getAccountsAsUser(String type, int userId) {
|
public Account[] getAccountsAsUser(String type, int userId) {
|
||||||
final int callingUid = Binder.getCallingUid();
|
return getAccountsAsUser(type, userId, null, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Account[] getAccountsAsUser(String type, int userId, String callingPackage,
|
||||||
|
int packageUid) {
|
||||||
|
int callingUid = Binder.getCallingUid();
|
||||||
// Only allow the system process to read accounts of other users
|
// Only allow the system process to read accounts of other users
|
||||||
if (userId != UserHandle.getCallingUserId()
|
if (userId != UserHandle.getCallingUserId()
|
||||||
&& callingUid != android.os.Process.myUid()) {
|
&& callingUid != Process.myUid()) {
|
||||||
throw new SecurityException("User " + UserHandle.getCallingUserId()
|
throw new SecurityException("User " + UserHandle.getCallingUserId()
|
||||||
+ " trying to get account for " + userId);
|
+ " trying to get account for " + userId);
|
||||||
}
|
}
|
||||||
@ -1730,12 +1737,17 @@ public class AccountManagerService
|
|||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + Binder.getCallingUid()
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
|
// If the original calling app was using the framework account chooser activity, we'll
|
||||||
|
// be passed in the original caller's uid here, which is what should be used for filtering.
|
||||||
|
if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) {
|
||||||
|
callingUid = packageUid;
|
||||||
|
}
|
||||||
checkReadAccountsPermission();
|
checkReadAccountsPermission();
|
||||||
UserAccounts accounts = getUserAccounts(userId);
|
UserAccounts accounts = getUserAccounts(userId);
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
synchronized (accounts.cacheLock) {
|
synchronized (accounts.cacheLock) {
|
||||||
return getAccountsFromCacheLocked(accounts, type, callingUid);
|
return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
restoreCallingIdentity(identityToken);
|
restoreCallingIdentity(identityToken);
|
||||||
@ -1806,6 +1818,16 @@ public class AccountManagerService
|
|||||||
return getAccountsAsUser(type, UserHandle.getCallingUserId());
|
return getAccountsAsUser(type, UserHandle.getCallingUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account[] getAccountsForPackage(String packageName, int uid) {
|
||||||
|
int callingUid = Binder.getCallingUid();
|
||||||
|
if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
|
||||||
|
throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
|
||||||
|
+ callingUid + " with uid=" + uid);
|
||||||
|
}
|
||||||
|
return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid);
|
||||||
|
}
|
||||||
|
|
||||||
public void getAccountsByFeatures(IAccountManagerResponse response,
|
public void getAccountsByFeatures(IAccountManagerResponse response,
|
||||||
String type, String[] features) {
|
String type, String[] features) {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
@ -1825,7 +1847,7 @@ public class AccountManagerService
|
|||||||
if (features == null || features.length == 0) {
|
if (features == null || features.length == 0) {
|
||||||
Account[] accounts;
|
Account[] accounts;
|
||||||
synchronized (userAccounts.cacheLock) {
|
synchronized (userAccounts.cacheLock) {
|
||||||
accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid);
|
accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null);
|
||||||
}
|
}
|
||||||
Bundle result = new Bundle();
|
Bundle result = new Bundle();
|
||||||
result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
|
result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
|
||||||
@ -2348,7 +2370,7 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
|
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
|
||||||
android.os.Process.myUid());
|
Process.myUid(), null);
|
||||||
fout.println("Accounts: " + accounts.length);
|
fout.println("Accounts: " + accounts.length);
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
fout.println(" " + account);
|
fout.println(" " + account);
|
||||||
@ -2501,7 +2523,7 @@ public class AccountManagerService
|
|||||||
|
|
||||||
private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
|
private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
|
||||||
int callerUid) {
|
int callerUid) {
|
||||||
if (callerUid == android.os.Process.SYSTEM_UID) {
|
if (callerUid == Process.SYSTEM_UID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
@ -2554,8 +2576,10 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean canUserModifyAccounts(int callingUid) {
|
private boolean canUserModifyAccounts(int callingUid) {
|
||||||
if (callingUid != android.os.Process.myUid()) {
|
if (callingUid != Process.myUid()) {
|
||||||
if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
|
if (getUserManager().getUserRestrictions(
|
||||||
|
new UserHandle(UserHandle.getUserId(callingUid)))
|
||||||
|
.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2566,7 +2590,7 @@ public class AccountManagerService
|
|||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
final int callingUid = getCallingUid();
|
final int callingUid = getCallingUid();
|
||||||
|
|
||||||
if (callingUid != android.os.Process.SYSTEM_UID) {
|
if (callingUid != Process.SYSTEM_UID) {
|
||||||
throw new SecurityException();
|
throw new SecurityException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2686,9 +2710,9 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered,
|
private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered,
|
||||||
int callingUid) {
|
int callingUid, String callingPackage) {
|
||||||
if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
|
if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
|
||||||
|| callingUid == android.os.Process.myUid()) {
|
|| callingUid == Process.myUid()) {
|
||||||
return unfiltered;
|
return unfiltered;
|
||||||
}
|
}
|
||||||
if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) {
|
if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) {
|
||||||
@ -2712,6 +2736,10 @@ public class AccountManagerService
|
|||||||
PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
|
PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
|
||||||
if (pi != null && pi.restrictedAccountType != null) {
|
if (pi != null && pi.restrictedAccountType != null) {
|
||||||
requiredAccountType = pi.restrictedAccountType;
|
requiredAccountType = pi.restrictedAccountType;
|
||||||
|
// If it matches the package name of the original caller, use this choice.
|
||||||
|
if (callingPackage != null && packageName.equals(callingPackage)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NameNotFoundException nnfe) {
|
} catch (NameNotFoundException nnfe) {
|
||||||
@ -2740,15 +2768,19 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* packageName can be null. If not null, it should be used to filter out restricted accounts
|
||||||
|
* that the package is not allowed to access.
|
||||||
|
*/
|
||||||
protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
|
protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
|
||||||
int callingUid) {
|
int callingUid, String callingPackage) {
|
||||||
if (accountType != null) {
|
if (accountType != null) {
|
||||||
final Account[] accounts = userAccounts.accountCache.get(accountType);
|
final Account[] accounts = userAccounts.accountCache.get(accountType);
|
||||||
if (accounts == null) {
|
if (accounts == null) {
|
||||||
return EMPTY_ACCOUNT_ARRAY;
|
return EMPTY_ACCOUNT_ARRAY;
|
||||||
} else {
|
} else {
|
||||||
return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
|
return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
|
||||||
callingUid);
|
callingUid, callingPackage);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int totalLength = 0;
|
int totalLength = 0;
|
||||||
@ -2765,7 +2797,7 @@ public class AccountManagerService
|
|||||||
accountsOfType.length);
|
accountsOfType.length);
|
||||||
totalLength += accountsOfType.length;
|
totalLength += accountsOfType.length;
|
||||||
}
|
}
|
||||||
return filterSharedAccounts(userAccounts, accounts, callingUid);
|
return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user