summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/accounts/AccountManager.java21
-rw-r--r--core/java/android/accounts/ChooseTypeAndAccountActivity.java49
-rw-r--r--core/java/android/accounts/IAccountManager.aidl5
-rw-r--r--core/java/android/os/UserManager.java8
-rw-r--r--core/res/res/layout/app_not_authorized.xml56
-rw-r--r--core/res/res/values/strings.xml7
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java6
-rw-r--r--services/java/com/android/server/accounts/AccountManagerService.java80
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);
}
}