Merge "[base] Fix logic around overriding DO when there are accounts on device." into udc-dev

This commit is contained in:
Jonathan Scott
2023-04-17 14:09:01 +00:00
committed by Android (Google) Code Review
4 changed files with 109 additions and 48 deletions

View File

@@ -538,6 +538,7 @@ package android.app.admin {
public class DevicePolicyManager {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void acknowledgeNewUserDisclaimer();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void calculateHasIncompatibleAccounts();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void clearOrganizationId();
method @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD) public void clearSystemUpdatePolicyFreezePeriodRecord();
method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceNetworkLogs();

View File

@@ -16824,6 +16824,23 @@ public class DevicePolicyManager {
}
}
/**
* Recalculate the incompatible accounts cache.
*
* @hide
*/
@TestApi
@RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
public void calculateHasIncompatibleAccounts() {
if (mService != null) {
try {
mService.calculateHasIncompatibleAccounts();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* @return {@code true} if bypassing the device policy management role qualification is allowed
* with the current state of the device.

View File

@@ -608,4 +608,6 @@ interface IDevicePolicyManager {
boolean isDeviceFinanced(String callerPackageName);
String getFinancedDeviceKioskRoleHolder(String callerPackageName);
void calculateHasIncompatibleAccounts();
}

View File

@@ -85,6 +85,7 @@ import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
import static android.accounts.AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
@@ -532,6 +533,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -1140,6 +1142,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
}
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
calculateHasIncompatibleAccounts();
}
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
&& userHandle == mOwners.getDeviceOwnerUserId()) {
mBugreportCollectionManager.checkForPendingBugreportAfterBoot();
@@ -1253,6 +1260,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)) {
notifyIfManagedSubscriptionsAreUnavailable(
UserHandle.of(userHandle), /* managedProfileAvailable= */ true);
} else if (LOGIN_ACCOUNTS_CHANGED_ACTION.equals(action)) {
calculateHasIncompatibleAccounts();
}
}
@@ -2105,6 +2114,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
filter.addAction(Intent.ACTION_USER_STOPPED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
filter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION);
filter.addAction(ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(ACTION_MANAGED_PROFILE_AVAILABLE);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
@@ -9560,6 +9570,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (getLockObject()) {
enforceCanSetDeviceOwnerLocked(caller, admin, userId, hasIncompatibleAccountsOrNonAdb);
Preconditions.checkArgument(isPackageInstalledForUser(admin.getPackageName(), userId),
"Invalid component " + admin + " for device owner");
final ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(admin, userId);
@@ -18386,6 +18397,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return isUserAffiliatedWithDeviceLocked(userId);
}
private boolean hasIncompatibleAccountsOnAnyUser() {
if (mHasIncompatibleAccounts == null) {
// Hasn't loaded for the first time yet - assume the worst
return true;
}
for (boolean hasIncompatible : mHasIncompatibleAccounts.values()) {
if (hasIncompatible) {
return true;
}
}
return false;
}
private boolean hasIncompatibleAccounts(int userId) {
return mHasIncompatibleAccounts == null ? true
: mHasIncompatibleAccounts.getOrDefault(userId, /* default= */ false);
}
/**
* Return true if a given user has any accounts that'll prevent installing a device or profile
* owner {@code owner}.
@@ -18423,7 +18454,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
boolean compatible = !hasIncompatibleAccounts(am, accounts);
boolean compatible = !hasIncompatibleAccounts(userId);
if (compatible) {
Slogf.w(LOG_TAG, "All accounts are compatible");
} else {
@@ -18433,37 +18464,67 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
});
}
private boolean hasIncompatibleAccounts(AccountManager am, Account[] accounts) {
// TODO(b/244284408): Add test
final String[] feature_allow =
{ DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED };
final String[] feature_disallow =
{ DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED };
for (Account account : accounts) {
if (hasAccountFeatures(am, account, feature_disallow)) {
Slogf.e(LOG_TAG, "%s has %s", account, feature_disallow[0]);
return true;
}
if (!hasAccountFeatures(am, account, feature_allow)) {
Slogf.e(LOG_TAG, "%s doesn't have %s", account, feature_allow[0]);
return true;
}
}
return false;
@Override
public void calculateHasIncompatibleAccounts() {
new CalculateHasIncompatibleAccountsTask().executeOnExecutor(
AsyncTask.THREAD_POOL_EXECUTOR, null);
}
private boolean hasAccountFeatures(AccountManager am, Account account, String[] features) {
try {
// TODO(267156507): Restore without blocking binder thread
return false;
// return am.hasFeatures(account, features, null, null).getResult();
} catch (Exception e) {
Slogf.w(LOG_TAG, "Failed to get account feature", e);
@Nullable
private volatile Map<Integer, Boolean> mHasIncompatibleAccounts;
class CalculateHasIncompatibleAccountsTask extends AsyncTask<
Void, Void, Map<Integer, Boolean>> {
private static final String[] FEATURE_ALLOW =
{DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED};
private static final String[] FEATURE_DISALLOW =
{DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED};
@Override
protected Map<Integer, Boolean> doInBackground(Void... args) {
List<UserInfo> users = mUserManagerInternal.getUsers(/* excludeDying= */ true);
Map<Integer, Boolean> results = new HashMap<>();
for (UserInfo userInfo : users) {
results.put(userInfo.id, userHasIncompatibleAccounts(userInfo.id));
}
return results;
}
private boolean userHasIncompatibleAccounts(int id) {
AccountManager am = mContext.createContextAsUser(UserHandle.of(id), /* flags= */ 0)
.getSystemService(AccountManager.class);
Account[] accounts = am.getAccounts();
for (Account account : accounts) {
if (hasAccountFeatures(am, account, FEATURE_DISALLOW)) {
return true;
}
if (!hasAccountFeatures(am, account, FEATURE_ALLOW)) {
return true;
}
}
return false;
}
}
@Override
protected void onPostExecute(Map<Integer, Boolean> results) {
mHasIncompatibleAccounts = Collections.unmodifiableMap(results);
Slogf.i(LOG_TAG, "Finished calculating hasIncompatibleAccountsTask");
}
private static boolean hasAccountFeatures(AccountManager am, Account account,
String[] features) {
try {
return am.hasFeatures(account, features, null, null).getResult();
} catch (Exception e) {
Slogf.w(LOG_TAG, "Failed to get account feature", e);
return false;
}
}
};
private boolean isAdb(CallerIdentity caller) {
return isShellUid(caller) || isRootUid(caller);
@@ -22295,26 +22356,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
private boolean hasIncompatibleAccountsOnAnyUser() {
long callingIdentity = Binder.clearCallingIdentity();
try {
for (UserInfo user : mUserManagerInternal.getUsers(/* excludeDying= */ true)) {
AccountManager am = mContext.createContextAsUser(
UserHandle.of(user.id), /* flags= */ 0)
.getSystemService(AccountManager.class);
Account[] accounts = am.getAccounts();
if (hasIncompatibleAccounts(am, accounts)) {
return true;
}
}
return false;
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
}
private void setBypassDevicePolicyManagementRoleQualificationStateInternal(
String currentRoleHolder, boolean allowBypass) {
boolean stateChanged = false;