Merge "Make visible only accounts for which authenticator supports contacts operations for callers with READ_CONTACTS permission." into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d401163599
@@ -364,11 +364,19 @@ public class AccountManager {
|
|||||||
"android.accounts.key_legacy_visible";
|
"android.accounts.key_legacy_visible";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key to set visibility for applications targeting API level below
|
* Key to set visibility for applications which satisfy one of the following conditions:
|
||||||
* {@link android.os.Build.VERSION_CODES#O} with
|
* <ul>
|
||||||
* {@link android.Manifest.permission#GET_ACCOUNTS} permission, or applications with any
|
* <li>Target API level below {@link android.os.Build.VERSION_CODES#O} and have
|
||||||
* targeting API level with the same signature as authenticator. See
|
* deprecated {@link android.Manifest.permission#GET_ACCOUNTS} permission.
|
||||||
* {@link #getAccountVisibility}. If the value was not set by authenticator
|
* </li>
|
||||||
|
* <li> Have {@link android.Manifest.permission#GET_ACCOUNTS_PRIVILEGED} permission. </li>
|
||||||
|
* <li> Have the same signature as authenticator. </li>
|
||||||
|
* <li> Have {@link android.Manifest.permission#READ_CONTACTS} permission and
|
||||||
|
* account type may be associated with contacts data - (verified by
|
||||||
|
* {@link android.Manifest.permission#WRITE_CONTACTS} permission check for the authenticator).
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* See {@link #getAccountVisibility}. If the value was not set by authenticator
|
||||||
* {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used.
|
* {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used.
|
||||||
*/
|
*/
|
||||||
public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE =
|
public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE =
|
||||||
|
|||||||
@@ -652,20 +652,20 @@ public class AccountManagerService
|
|||||||
return visibility;
|
return visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isPrivileged = isPermittedForPackage(packageName, accounts.userId,
|
boolean isPrivileged = isPermittedForPackage(packageName, uid, accounts.userId,
|
||||||
Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
|
Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
|
||||||
|
|
||||||
// Device/Profile owner gets visibility by default.
|
// Device/Profile owner gets visibility by default.
|
||||||
if (isProfileOwner(uid)) {
|
if (isProfileOwner(uid)) {
|
||||||
return AccountManager.VISIBILITY_VISIBLE;
|
return AccountManager.VISIBILITY_VISIBLE;
|
||||||
}
|
}
|
||||||
// Apps with READ_CONTACTS permission get visibility by default even post O.
|
|
||||||
boolean canReadContacts = checkReadContactsPermission(packageName, accounts.userId);
|
|
||||||
|
|
||||||
boolean preO = isPreOApplication(packageName);
|
boolean preO = isPreOApplication(packageName);
|
||||||
if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH)
|
if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH)
|
||||||
|| (preO && checkGetAccountsPermission(packageName, accounts.userId))
|
|| (preO && checkGetAccountsPermission(packageName, uid, accounts.userId))
|
||||||
|| canReadContacts || isPrivileged) {
|
|| (checkReadContactsPermission(packageName, uid, accounts.userId)
|
||||||
|
&& accountTypeManagesContacts(account.type, accounts.userId))
|
||||||
|
|| isPrivileged) {
|
||||||
// Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
|
// Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
|
||||||
// match.
|
// match.
|
||||||
visibility = getAccountVisibilityFromCache(account,
|
visibility = getAccountVisibilityFromCache(account,
|
||||||
@@ -5022,14 +5022,20 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPermittedForPackage(String packageName, int userId, String... permissions) {
|
private boolean isPermittedForPackage(String packageName, int uid, int userId,
|
||||||
|
String... permissions) {
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
IPackageManager pm = ActivityThread.getPackageManager();
|
IPackageManager pm = ActivityThread.getPackageManager();
|
||||||
for (String perm : permissions) {
|
for (String perm : permissions) {
|
||||||
if (pm.checkPermission(perm, packageName, userId)
|
if (pm.checkPermission(perm, packageName, userId)
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
return true;
|
// Checks runtime permission revocation.
|
||||||
|
final int opCode = AppOpsManager.permissionToOpCode(perm);
|
||||||
|
if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp(
|
||||||
|
opCode, uid, packageName) == AppOpsManager.MODE_ALLOWED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -5145,13 +5151,37 @@ public class AccountManagerService
|
|||||||
// Method checks visibility for applications targeing API level below {@link
|
// Method checks visibility for applications targeing API level below {@link
|
||||||
// android.os.Build.VERSION_CODES#O},
|
// android.os.Build.VERSION_CODES#O},
|
||||||
// returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVILEGED permission.
|
// returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVILEGED permission.
|
||||||
private boolean checkGetAccountsPermission(String packageName, int userId) {
|
private boolean checkGetAccountsPermission(String packageName, int uid, int userId) {
|
||||||
return isPermittedForPackage(packageName, userId, Manifest.permission.GET_ACCOUNTS,
|
return isPermittedForPackage(packageName, uid, userId, Manifest.permission.GET_ACCOUNTS,
|
||||||
Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
|
Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkReadContactsPermission(String packageName, int userId) {
|
private boolean checkReadContactsPermission(String packageName, int uid, int userId) {
|
||||||
return isPermittedForPackage(packageName, userId, Manifest.permission.READ_CONTACTS);
|
return isPermittedForPackage(packageName, uid, userId, Manifest.permission.READ_CONTACTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heuristic to check that account type may be associated with some contacts data and
|
||||||
|
// therefore READ_CONTACTS permission grants the access to account by default.
|
||||||
|
private boolean accountTypeManagesContacts(String accountType, int userId) {
|
||||||
|
if (accountType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long identityToken = Binder.clearCallingIdentity();
|
||||||
|
Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> serviceInfos;
|
||||||
|
try {
|
||||||
|
serviceInfos = mAuthenticatorCache.getAllServices(userId);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identityToken);
|
||||||
|
}
|
||||||
|
// Check contacts related permissions for authenticator.
|
||||||
|
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo
|
||||||
|
: serviceInfos) {
|
||||||
|
if (accountType.equals(serviceInfo.type.type)) {
|
||||||
|
return isPermittedForPackage(serviceInfo.type.packageName, serviceInfo.uid, userId,
|
||||||
|
Manifest.permission.WRITE_CONTACTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user