diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/accounts/AccountManager.java | 21 | ||||
| -rw-r--r-- | core/java/android/accounts/ChooseTypeAndAccountActivity.java | 49 | ||||
| -rw-r--r-- | core/java/android/accounts/IAccountManager.aidl | 5 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 8 | ||||
| -rw-r--r-- | core/res/res/layout/app_not_authorized.xml | 56 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 7 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 3 | ||||
| -rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 2 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java | 6 | ||||
| -rw-r--r-- | services/java/com/android/server/accounts/AccountManagerService.java | 80 |
11 files changed, 197 insertions, 41 deletions
diff --git a/api/current.txt b/api/current.txt index 6f0575c88a82..31acb354cfdf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16984,6 +16984,7 @@ package android.os { } public class UserManager { + method public static synchronized android.os.UserManager get(android.content.Context); method public long getSerialNumberForUser(android.os.UserHandle); method public int getUserCount(); method public android.os.UserHandle getUserForSerialNumber(long); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index bdc882ac7fe6..241a64af65ae 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -388,6 +388,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 * string token corresponding to the authenticator and useful domain * of the account. For example, there are types corresponding to Google @@ -575,7 +592,7 @@ public class AccountManager { public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { if (account == null) throw new IllegalArgumentException("account is null"); try { - return mService.addAccount(account, password, userdata); + return mService.addAccountExplicitly(account, password, userdata); } catch (RemoteException e) { // won't ever happen throw new RuntimeException(e); @@ -1123,7 +1140,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { - mService.addAcount(mResponse, accountType, authTokenType, + mService.addAccount(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn); } }.start(); diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 5358bc796ab9..2aba16339a34 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -18,9 +18,14 @@ package android.accounts; import com.google.android.collect.Sets; import android.app.Activity; +import android.app.ActivityManagerNative; import android.content.Intent; import android.os.Bundle; +import android.os.IBinder; import android.os.Parcelable; +import android.os.RemoteException; +import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -29,6 +34,7 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; +import android.widget.Toast; import com.android.internal.R; @@ -119,6 +125,9 @@ public class ChooseTypeAndAccountActivity extends Activity private Parcelable[] mExistingAccounts = null; private int mSelectedItemIndex; private Button mOkButton; + private int mCallingUid; + private String mCallingPackage; + private boolean mDisallowAddAccounts; @Override public void onCreate(Bundle savedInstanceState) { @@ -128,6 +137,24 @@ public class ChooseTypeAndAccountActivity extends Activity + 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 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 // add account. Otherwise let the user choose. if (mAccounts.isEmpty()) { + if (mDisallowAddAccounts) { + setContentView(R.layout.app_not_authorized); + setTitle(R.string.error_message_title); + return; + } if (mSetOfRelevantAccountTypes.size() == 1) { runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next()); } else { @@ -296,7 +328,8 @@ public class ChooseTypeAndAccountActivity extends Activity } 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>(); for (Parcelable accountParcel : mExistingAccounts) { preExistingAccounts.add((Account) accountParcel); @@ -347,7 +380,8 @@ public class ChooseTypeAndAccountActivity extends Activity AccountManager.KEY_INTENT); if (intent != null) { 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); startActivityForResult(intent, REQUEST_ADD_ACCOUNT); return; @@ -424,12 +458,14 @@ public class ChooseTypeAndAccountActivity extends Activity private String[] getListOfDisplayableOptions(ArrayList<Account> accounts) { // List of options includes all accounts found together with "Add new account" as the // 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++) { listItems[i] = accounts.get(i).name; } - listItems[accounts.size()] = getResources().getString( - R.string.add_account_button_label); + if (!mDisallowAddAccounts) { + listItems[accounts.size()] = getResources().getString( + R.string.add_account_button_label); + } return listItems; } @@ -439,7 +475,8 @@ public class ChooseTypeAndAccountActivity extends Activity * allowable accounts, if provided. */ 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); for (Account account : accounts) { if (mSetOfAllowableAccounts != null diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 47b257d7241a..81418132d5c8 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -31,10 +31,11 @@ interface IAccountManager { String getUserData(in Account account, String key); AuthenticatorDescription[] getAuthenticatorTypes(); Account[] getAccounts(String accountType); + Account[] getAccountsForPackage(String packageName, int uid); Account[] getAccountsAsUser(String accountType, int userId); void hasFeatures(in IAccountManagerResponse response, in Account account, 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 invalidateAuthToken(String accountType, String authToken); String peekAuthToken(in Account account, String authTokenType); @@ -47,7 +48,7 @@ interface IAccountManager { void getAuthToken(in IAccountManagerResponse response, in Account account, String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch, in Bundle options); - void addAcount(in IAccountManagerResponse response, String accountType, + void addAccount(in IAccountManagerResponse response, String accountType, String authTokenType, in String[] requiredFeatures, boolean expectActivityLaunch, in Bundle options); void updateCredentials(in IAccountManagerResponse response, in Account account, diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 1ba16bd1430d..b9b8f083ba1a 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -121,6 +121,14 @@ public class UserManager { */ 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 */ public UserManager(Context context, IUserManager service) { diff --git a/core/res/res/layout/app_not_authorized.xml b/core/res/res/layout/app_not_authorized.xml new file mode 100644 index 000000000000..bd40eeb0b31d --- /dev/null +++ b/core/res/res/layout/app_not_authorized.xml @@ -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> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9e106612b046..4a159671a739 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4063,5 +4063,10 @@ <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] --> <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> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 81baaf850c4a..757bbc8f73b0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -869,7 +869,7 @@ <java-symbol type="string" name="config_chooseAccountActivity" /> <java-symbol type="string" name="config_chooseTypeAndAccountActivity" /> <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_hours" /> @@ -1121,6 +1121,7 @@ <java-symbol type="layout" name="sms_short_code_confirmation_dialog" /> <java-symbol type="layout" name="keyguard_add_widget" /> <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_right" /> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 45319a856904..659651b887c4 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -322,7 +322,7 @@ public class SettingsProvider extends ContentProvider { @Override public boolean onCreate() { mBackupManager = new BackupManager(getContext()); - mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + mUserManager = UserManager.get(getContext()); setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS); establishDbTracking(UserHandle.USER_OWNER); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index 60e22c57a65b..a7c7fba68c52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -206,8 +206,7 @@ class QuickSettings { mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() { @Override protected Pair<String, Drawable> doInBackground(Void... params) { - final UserManager um = - (UserManager) mContext.getSystemService(Context.USER_SERVICE); + final UserManager um = UserManager.get(mContext); // Fall back to the UserManager nickname if we can't read the name from the local // profile below. @@ -292,8 +291,7 @@ class QuickSettings { @Override public void onClick(View v) { mBar.collapseAllPanels(true); - final UserManager um = - (UserManager) mContext.getSystemService(Context.USER_SERVICE); + final UserManager um = UserManager.get(mContext); if (um.getUsers(true).size() > 1) { try { WindowManagerGlobal.getWindowManagerService().lockNow(null); diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index 944bf33b0267..5009793da3fa 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -58,6 +58,7 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -270,7 +271,7 @@ public class AccountManagerService private UserManager getUserManager() { if (mUserManager == null) { - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mUserManager = UserManager.get(mContext); } return mUserManager; } @@ -542,9 +543,9 @@ public class AccountManagerService } @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)) { - Log.v(TAG, "addAccount: " + account + Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid()); } @@ -1167,7 +1168,7 @@ public class AccountManagerService final int callingUid = getCallingUid(); clearCallingIdentity(); - if (callingUid != android.os.Process.SYSTEM_UID) { + if (callingUid != Process.SYSTEM_UID) { throw new SecurityException("can only call from system"); } UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid)); @@ -1395,7 +1396,7 @@ public class AccountManagerService 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 boolean expectActivityLaunch, final Bundle optionsIn) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -1412,7 +1413,7 @@ public class AccountManagerService checkManageAccountsPermission(); // Is user disallowed from modifying accounts? - if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { + if (!canUserModifyAccounts(Binder.getCallingUid())) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -1457,7 +1458,7 @@ public class AccountManagerService int userId) { // Only allow the system process to read accounts of other users if (userId != UserHandle.getCallingUserId() - && Binder.getCallingUid() != android.os.Process.myUid()) { + && Binder.getCallingUid() != Process.myUid()) { throw new SecurityException("User " + UserHandle.getCallingUserId() + " trying to confirm account credentials for " + userId); } @@ -1573,7 +1574,8 @@ public class AccountManagerService public void run() throws RemoteException { synchronized (mAccounts.cacheLock) { - mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid); + mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid, + null); } // check whether each account matches the requested features mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length); @@ -1662,7 +1664,7 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { synchronized (accounts.cacheLock) { - return getAccountsFromCacheLocked(accounts, null, callingUid); + return getAccountsFromCacheLocked(accounts, null, callingUid, null); } } finally { restoreCallingIdentity(identityToken); @@ -1703,7 +1705,7 @@ public class AccountManagerService if (userAccounts == null) continue; synchronized (userAccounts.cacheLock) { Account[] accounts = getAccountsFromCacheLocked(userAccounts, null, - Binder.getCallingUid()); + Binder.getCallingUid(), null); for (int a = 0; a < accounts.length; a++) { runningAccounts.add(new AccountAndUser(accounts[a], userId)); } @@ -1717,10 +1719,15 @@ public class AccountManagerService @Override 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 if (userId != UserHandle.getCallingUserId() - && callingUid != android.os.Process.myUid()) { + && callingUid != Process.myUid()) { throw new SecurityException("User " + UserHandle.getCallingUserId() + " trying to get account for " + userId); } @@ -1730,12 +1737,17 @@ public class AccountManagerService + ", caller's uid " + Binder.getCallingUid() + ", 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(); UserAccounts accounts = getUserAccounts(userId); long identityToken = clearCallingIdentity(); try { synchronized (accounts.cacheLock) { - return getAccountsFromCacheLocked(accounts, type, callingUid); + return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage); } } finally { restoreCallingIdentity(identityToken); @@ -1806,6 +1818,16 @@ public class AccountManagerService 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, String type, String[] features) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -1825,7 +1847,7 @@ public class AccountManagerService if (features == null || features.length == 0) { Account[] accounts; synchronized (userAccounts.cacheLock) { - accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid); + accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null); } Bundle result = new Bundle(); result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts); @@ -2348,7 +2370,7 @@ public class AccountManagerService } } else { Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */, - android.os.Process.myUid()); + Process.myUid(), null); fout.println("Accounts: " + accounts.length); for (Account account : accounts) { fout.println(" " + account); @@ -2501,7 +2523,7 @@ public class AccountManagerService private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType, int callerUid) { - if (callerUid == android.os.Process.SYSTEM_UID) { + if (callerUid == Process.SYSTEM_UID) { return true; } UserAccounts accounts = getUserAccountsForCaller(); @@ -2554,8 +2576,10 @@ public class AccountManagerService } private boolean canUserModifyAccounts(int callingUid) { - if (callingUid != android.os.Process.myUid()) { - if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { + if (callingUid != Process.myUid()) { + if (getUserManager().getUserRestrictions( + new UserHandle(UserHandle.getUserId(callingUid))) + .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { return false; } } @@ -2566,7 +2590,7 @@ public class AccountManagerService throws RemoteException { final int callingUid = getCallingUid(); - if (callingUid != android.os.Process.SYSTEM_UID) { + if (callingUid != Process.SYSTEM_UID) { throw new SecurityException(); } @@ -2686,9 +2710,9 @@ public class AccountManagerService } private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered, - int callingUid) { + int callingUid, String callingPackage) { if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0 - || callingUid == android.os.Process.myUid()) { + || callingUid == Process.myUid()) { return unfiltered; } if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) { @@ -2712,6 +2736,10 @@ public class AccountManagerService PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); if (pi != null && pi.restrictedAccountType != null) { 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) { @@ -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, - int callingUid) { + int callingUid, String callingPackage) { if (accountType != null) { final Account[] accounts = userAccounts.accountCache.get(accountType); if (accounts == null) { return EMPTY_ACCOUNT_ARRAY; } else { return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length), - callingUid); + callingUid, callingPackage); } } else { int totalLength = 0; @@ -2765,7 +2797,7 @@ public class AccountManagerService accountsOfType.length); totalLength += accountsOfType.length; } - return filterSharedAccounts(userAccounts, accounts, callingUid); + return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage); } } |