Loading services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +37 −179 Original line number Diff line number Diff line Loading @@ -31,16 +31,13 @@ import static android.os.UserHandle.getCallingUserId; import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.Preconditions.checkState; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature; import static com.android.server.companion.utils.PackageUtils.getPackageInfo; import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerIsSystemOr; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerIsSystemOrCanInteractWithUserId; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MINUTES; import android.annotation.EnforcePermission; import android.annotation.NonNull; Loading Loading @@ -69,31 +66,22 @@ import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.net.MacAddress; import android.net.NetworkPolicyManager; import android.os.Binder; import android.os.Environment; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PowerExemptionManager; import android.os.PowerManagerInternal; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.permission.flags.Flags; import android.util.ArraySet; import android.util.ExceptionUtils; import android.util.Slog; import com.android.internal.app.IAppOpsService; import com.android.internal.content.PackageMonitor; import com.android.internal.notification.NotificationAccessConfirmationActivityContract; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.server.FgThread; Loading @@ -114,35 +102,27 @@ import com.android.server.companion.devicepresence.DevicePresenceProcessor; import com.android.server.companion.devicepresence.ObservableUuid; import com.android.server.companion.devicepresence.ObservableUuidStore; import com.android.server.companion.transport.CompanionTransportManager; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @SuppressLint("LongLogTag") public class CompanionDeviceManagerService extends SystemService { private static final String TAG = "CDM_CompanionDeviceManagerService"; private static final long PAIR_WITHOUT_PROMPT_WINDOW_MS = 10 * 60 * 1000; // 10 min private static final String PREF_FILE_NAME = "companion_device_preferences.xml"; private static final String PREF_KEY_AUTO_REVOKE_GRANTS_DONE = "auto_revoke_grants_done"; private static final int MAX_CN_LENGTH = 500; private final ActivityTaskManagerInternal mAtmInternal; private final ActivityManagerInternal mAmInternal; private final IAppOpsService mAppOpsManager; private final PowerExemptionManager mPowerExemptionManager; private final PackageManagerInternal mPackageManagerInternal; private final AssociationStore mAssociationStore; private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private final ObservableUuidStore mObservableUuidStore; private final CompanionExemptionProcessor mCompanionExemptionProcessor; private final AssociationRequestsProcessor mAssociationRequestsProcessor; private final SystemDataTransferProcessor mSystemDataTransferProcessor; private final BackupRestoreProcessor mBackupRestoreProcessor; Loading @@ -156,12 +136,15 @@ public class CompanionDeviceManagerService extends SystemService { super(context); final ActivityManager activityManager = context.getSystemService(ActivityManager.class); mPowerExemptionManager = context.getSystemService(PowerExemptionManager.class); mAppOpsManager = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mAmInternal = LocalServices.getService(ActivityManagerInternal.class); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); final PowerExemptionManager powerExemptionManager = context.getSystemService( PowerExemptionManager.class); final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); final ActivityTaskManagerInternal atmInternal = LocalServices.getService( ActivityTaskManagerInternal.class); final ActivityManagerInternal amInternal = LocalServices.getService( ActivityManagerInternal.class); final PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); final UserManager userManager = context.getSystemService(UserManager.class); final PowerManagerInternal powerManagerInternal = LocalServices.getService( PowerManagerInternal.class); Loading @@ -173,25 +156,29 @@ public class CompanionDeviceManagerService extends SystemService { // Init processors mAssociationRequestsProcessor = new AssociationRequestsProcessor(context, mPackageManagerInternal, mAssociationStore); mBackupRestoreProcessor = new BackupRestoreProcessor(context, mPackageManagerInternal, packageManagerInternal, mAssociationStore); mBackupRestoreProcessor = new BackupRestoreProcessor(context, packageManagerInternal, mAssociationStore, associationDiskStore, mSystemDataTransferRequestStore, mAssociationRequestsProcessor); mCompanionAppBinder = new CompanionAppBinder(context); mCompanionExemptionProcessor = new CompanionExemptionProcessor(context, powerExemptionManager, appOpsManager, packageManagerInternal, atmInternal, amInternal, mAssociationStore); mDevicePresenceProcessor = new DevicePresenceProcessor(context, mCompanionAppBinder, userManager, mAssociationStore, mObservableUuidStore, powerManagerInternal); powerManagerInternal, mCompanionExemptionProcessor); mTransportManager = new CompanionTransportManager(context, mAssociationStore); mDisassociationProcessor = new DisassociationProcessor(context, activityManager, mAssociationStore, mPackageManagerInternal, mDevicePresenceProcessor, mAssociationStore, packageManagerInternal, mDevicePresenceProcessor, mCompanionAppBinder, mSystemDataTransferRequestStore, mTransportManager); mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mPackageManagerInternal, mAssociationStore, packageManagerInternal, mAssociationStore, mSystemDataTransferRequestStore, mTransportManager); // TODO(b/279663946): move context sync to a dedicated system service Loading @@ -202,7 +189,6 @@ public class CompanionDeviceManagerService extends SystemService { public void onStart() { // Init association stores mAssociationStore.refreshCache(); mAssociationStore.registerLocalListener(mAssociationStoreChangeListener); // Init UUID store mObservableUuidStore.getObservableUuidsForUser(getContext().getUserId()); Loading Loading @@ -240,11 +226,11 @@ public class CompanionDeviceManagerService extends SystemService { if (associations.isEmpty()) return; updateAtm(userId, associations); mCompanionExemptionProcessor.updateAtm(userId, associations); BackgroundThread.getHandler().sendMessageDelayed( obtainMessage(CompanionDeviceManagerService::maybeGrantAutoRevokeExemptions, this), MINUTES.toMillis(10)); try (ExecutorService executor = Executors.newSingleThreadExecutor()) { executor.execute(mCompanionExemptionProcessor::updateAutoRevokeExemptions); } } @Override Loading @@ -262,30 +248,30 @@ public class CompanionDeviceManagerService extends SystemService { if (!associationsForPackage.isEmpty()) { Slog.i(TAG, "Package removed or data cleared for user=[" + userId + "], package=[" + packageName + "]. Cleaning up CDM data..."); } for (AssociationInfo association : associationsForPackage) { mDisassociationProcessor.disassociate(association.getId()); } mCompanionAppBinder.onPackagesChanged(userId, packageName); } // Clear observable UUIDs for the package. final List<ObservableUuid> uuidsTobeObserved = mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); for (ObservableUuid uuid : uuidsTobeObserved) { mObservableUuidStore.removeObservableUuid(userId, uuid.getUuid(), packageName); } mCompanionAppBinder.onPackagesChanged(userId); } private void onPackageModifiedInternal(@UserIdInt int userId, @NonNull String packageName) { final List<AssociationInfo> associationsForPackage = final List<AssociationInfo> associations = mAssociationStore.getAssociationsByPackage(userId, packageName); for (AssociationInfo association : associationsForPackage) { updateSpecialAccessPermissionForAssociatedPackage(association.getUserId(), association.getPackageName()); } if (!associations.isEmpty()) { mCompanionExemptionProcessor.exemptPackage(userId, packageName, false); mCompanionAppBinder.onPackagesChanged(userId); mCompanionAppBinder.onPackagesChanged(userId, packageName); } } private void onPackageAddedInternal(@UserIdInt int userId, @NonNull String packageName) { Loading Loading @@ -765,130 +751,6 @@ public class CompanionDeviceManagerService extends SystemService { } } /** * Update special access for the association's package */ public void updateSpecialAccessPermissionForAssociatedPackage(int userId, String packageName) { final PackageInfo packageInfo = getPackageInfo(getContext(), userId, packageName); Binder.withCleanCallingIdentity(() -> updateSpecialAccessPermissionAsSystem(packageInfo)); } private void updateSpecialAccessPermissionAsSystem(PackageInfo packageInfo) { if (packageInfo == null) { return; } if (containsEither(packageInfo.requestedPermissions, android.Manifest.permission.RUN_IN_BACKGROUND, android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) { mPowerExemptionManager.addToPermanentAllowList(packageInfo.packageName); } else { try { mPowerExemptionManager.removeFromPermanentAllowList(packageInfo.packageName); } catch (UnsupportedOperationException e) { Slog.w(TAG, packageInfo.packageName + " can't be removed from power save" + " whitelist. It might due to the package is whitelisted by the system."); } } NetworkPolicyManager networkPolicyManager = NetworkPolicyManager.from(getContext()); try { if (containsEither(packageInfo.requestedPermissions, android.Manifest.permission.USE_DATA_IN_BACKGROUND, android.Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)) { networkPolicyManager.addUidPolicy( packageInfo.applicationInfo.uid, NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND); } else { networkPolicyManager.removeUidPolicy( packageInfo.applicationInfo.uid, NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND); } } catch (IllegalArgumentException e) { Slog.e(TAG, e.getMessage()); } exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid); } private void exemptFromAutoRevoke(String packageName, int uid) { try { mAppOpsManager.setMode( AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid, packageName, AppOpsManager.MODE_IGNORED); } catch (RemoteException e) { Slog.w(TAG, "Error while granting auto revoke exemption for " + packageName, e); } } private void updateAtm(int userId, List<AssociationInfo> associations) { final Set<Integer> companionAppUids = new ArraySet<>(); for (AssociationInfo association : associations) { final int uid = mPackageManagerInternal.getPackageUid(association.getPackageName(), 0, userId); if (uid >= 0) { companionAppUids.add(uid); } } if (mAtmInternal != null) { mAtmInternal.setCompanionAppUids(userId, companionAppUids); } if (mAmInternal != null) { // Make a copy of the set and send it to ActivityManager. mAmInternal.setCompanionAppUids(userId, new ArraySet<>(companionAppUids)); } } private void maybeGrantAutoRevokeExemptions() { Slog.d(TAG, "maybeGrantAutoRevokeExemptions()"); PackageManager pm = getContext().getPackageManager(); for (int userId : LocalServices.getService(UserManagerInternal.class).getUserIds()) { SharedPreferences pref = getContext().getSharedPreferences( new File(Environment.getUserSystemDirectory(userId), PREF_FILE_NAME), Context.MODE_PRIVATE); if (pref.getBoolean(PREF_KEY_AUTO_REVOKE_GRANTS_DONE, false)) { continue; } try { final List<AssociationInfo> associations = mAssociationStore.getActiveAssociationsByUser(userId); for (AssociationInfo a : associations) { try { int uid = pm.getPackageUidAsUser(a.getPackageName(), userId); exemptFromAutoRevoke(a.getPackageName(), uid); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Unknown companion package: " + a.getPackageName(), e); } } } finally { pref.edit().putBoolean(PREF_KEY_AUTO_REVOKE_GRANTS_DONE, true).apply(); } } } private final AssociationStore.OnChangeListener mAssociationStoreChangeListener = new AssociationStore.OnChangeListener() { @Override public void onAssociationChanged(int changeType, AssociationInfo association) { Slog.d(TAG, "onAssociationChanged changeType=[" + changeType + "], association=[" + association); final int userId = association.getUserId(); final List<AssociationInfo> updatedAssociations = mAssociationStore.getActiveAssociationsByUser(userId); updateAtm(userId, updatedAssociations); updateSpecialAccessPermissionForAssociatedPackage(association.getUserId(), association.getPackageName()); } }; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onPackageRemoved(String packageName, int uid) { Loading @@ -911,10 +773,6 @@ public class CompanionDeviceManagerService extends SystemService { } }; private static <T> boolean containsEither(T[] array, T a, T b) { return ArrayUtils.contains(array, a) || ArrayUtils.contains(array, b); } private class LocalService implements CompanionDeviceManagerServiceInternal { @Override Loading services/companion/java/com/android/server/companion/CompanionExemptionProcessor.java 0 → 100644 +219 −0 File added.Preview size limit exceeded, changes collapsed. Show changes services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java +4 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,10 @@ public class CompanionAppBinder { /** * On package changed. */ public void onPackagesChanged(@UserIdInt int userId) { public void onPackagesChanged(@UserIdInt int userId, String packageName) { // TODO: We shouldn't need to clean up the whole user registry. We only need to remove the // package. I will do it in a separate change since it's not appropriate to use // PerUser anymore. mCompanionServicesRegister.invalidate(userId); } Loading services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java +17 −10 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.CollectionUtils; import com.android.server.companion.CompanionExemptionProcessor; import com.android.server.companion.association.AssociationStore; import java.io.PrintWriter; Loading Loading @@ -101,6 +102,8 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene private final PowerManagerInternal mPowerManagerInternal; @NonNull private final UserManager mUserManager; @NonNull private final CompanionExemptionProcessor mCompanionExemptionProcessor; // NOTE: Same association may appear in more than one of the following sets at the same time. // (E.g. self-managed devices that have MAC addresses, could be reported as present by their Loading @@ -111,7 +114,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene @NonNull private final Set<Integer> mNearbyBleDevices = new HashSet<>(); @NonNull private final Set<Integer> mReportedSelfManagedDevices = new HashSet<>(); private final Set<Integer> mConnectedSelfManagedDevices = new HashSet<>(); @NonNull private final Set<ParcelUuid> mConnectedUuidDevices = new HashSet<>(); @NonNull Loading Loading @@ -146,7 +149,8 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene @NonNull UserManager userManager, @NonNull AssociationStore associationStore, @NonNull ObservableUuidStore observableUuidStore, @NonNull PowerManagerInternal powerManagerInternal) { @NonNull PowerManagerInternal powerManagerInternal, @NonNull CompanionExemptionProcessor companionExemptionProcessor) { mContext = context; mCompanionAppBinder = companionAppBinder; mAssociationStore = associationStore; Loading @@ -156,6 +160,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene mObservableUuidStore, this); mBleDeviceProcessor = new BleDeviceProcessor(associationStore, this); mPowerManagerInternal = powerManagerInternal; mCompanionExemptionProcessor = companionExemptionProcessor; } /** Initialize {@link DevicePresenceProcessor} */ Loading Loading @@ -404,7 +409,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * nearby (for "self-managed" associations). */ public boolean isDevicePresent(int associationId) { return mReportedSelfManagedDevices.contains(associationId) return mConnectedSelfManagedDevices.contains(associationId) || mConnectedBtDevices.contains(associationId) || mNearbyBleDevices.contains(associationId) || mSimulated.contains(associationId); Loading Loading @@ -451,7 +456,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * notifyDeviceAppeared()} */ public void onSelfManagedDeviceConnected(int associationId) { onDevicePresenceEvent(mReportedSelfManagedDevices, onDevicePresenceEvent(mConnectedSelfManagedDevices, associationId, EVENT_SELF_MANAGED_APPEARED); } Loading @@ -467,7 +472,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * notifyDeviceDisappeared()} */ public void onSelfManagedDeviceDisconnected(int associationId) { onDevicePresenceEvent(mReportedSelfManagedDevices, onDevicePresenceEvent(mConnectedSelfManagedDevices, associationId, EVENT_SELF_MANAGED_DISAPPEARED); } Loading @@ -475,7 +480,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * Marks a "self-managed" device as disconnected when binderDied. */ public void onSelfManagedDeviceReporterBinderDied(int associationId) { onDevicePresenceEvent(mReportedSelfManagedDevices, onDevicePresenceEvent(mConnectedSelfManagedDevices, associationId, EVENT_SELF_MANAGED_DISAPPEARED); } Loading Loading @@ -683,6 +688,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene if (association.shouldBindWhenPresent()) { bindApplicationIfNeeded(userId, packageName, association.isSelfManaged()); mCompanionExemptionProcessor.exemptPackage(userId, packageName, true); } else { return; } Loading Loading @@ -715,6 +721,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene // Check if there are other devices associated to the app that are present. if (!shouldBindPackage(userId, packageName)) { mCompanionAppBinder.unbindCompanionApp(userId, packageName); mCompanionExemptionProcessor.exemptPackage(userId, packageName, false); } break; default: Loading Loading @@ -940,7 +947,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene mConnectedBtDevices.remove(id); mNearbyBleDevices.remove(id); mReportedSelfManagedDevices.remove(id); mConnectedSelfManagedDevices.remove(id); mSimulated.remove(id); synchronized (mBtDisconnectedDevices) { mBtDisconnectedDevices.remove(id); Loading Loading @@ -1100,7 +1107,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene out.append("Companion Device Present: "); if (mConnectedBtDevices.isEmpty() && mNearbyBleDevices.isEmpty() && mReportedSelfManagedDevices.isEmpty()) { && mConnectedSelfManagedDevices.isEmpty()) { out.append("<empty>\n"); return; } else { Loading Loading @@ -1130,11 +1137,11 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene } out.append(" Self-Reported Devices: "); if (mReportedSelfManagedDevices.isEmpty()) { if (mConnectedSelfManagedDevices.isEmpty()) { out.append("<empty>\n"); } else { out.append("\n"); for (int associationId : mReportedSelfManagedDevices) { for (int associationId : mConnectedSelfManagedDevices) { AssociationInfo a = mAssociationStore.getAssociationById(associationId); out.append(" ").append(a.toShortString()).append('\n'); } Loading Loading
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +37 −179 Original line number Diff line number Diff line Loading @@ -31,16 +31,13 @@ import static android.os.UserHandle.getCallingUserId; import static com.android.internal.util.CollectionUtils.any; import static com.android.internal.util.Preconditions.checkState; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.companion.utils.PackageUtils.enforceUsesCompanionDeviceFeature; import static com.android.server.companion.utils.PackageUtils.getPackageInfo; import static com.android.server.companion.utils.PackageUtils.isRestrictedSettingsAllowed; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerCanManageAssociationsForPackage; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerIsSystemOr; import static com.android.server.companion.utils.PermissionsUtils.enforceCallerIsSystemOrCanInteractWithUserId; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MINUTES; import android.annotation.EnforcePermission; import android.annotation.NonNull; Loading Loading @@ -69,31 +66,22 @@ import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.net.MacAddress; import android.net.NetworkPolicyManager; import android.os.Binder; import android.os.Environment; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PowerExemptionManager; import android.os.PowerManagerInternal; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.permission.flags.Flags; import android.util.ArraySet; import android.util.ExceptionUtils; import android.util.Slog; import com.android.internal.app.IAppOpsService; import com.android.internal.content.PackageMonitor; import com.android.internal.notification.NotificationAccessConfirmationActivityContract; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.server.FgThread; Loading @@ -114,35 +102,27 @@ import com.android.server.companion.devicepresence.DevicePresenceProcessor; import com.android.server.companion.devicepresence.ObservableUuid; import com.android.server.companion.devicepresence.ObservableUuidStore; import com.android.server.companion.transport.CompanionTransportManager; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @SuppressLint("LongLogTag") public class CompanionDeviceManagerService extends SystemService { private static final String TAG = "CDM_CompanionDeviceManagerService"; private static final long PAIR_WITHOUT_PROMPT_WINDOW_MS = 10 * 60 * 1000; // 10 min private static final String PREF_FILE_NAME = "companion_device_preferences.xml"; private static final String PREF_KEY_AUTO_REVOKE_GRANTS_DONE = "auto_revoke_grants_done"; private static final int MAX_CN_LENGTH = 500; private final ActivityTaskManagerInternal mAtmInternal; private final ActivityManagerInternal mAmInternal; private final IAppOpsService mAppOpsManager; private final PowerExemptionManager mPowerExemptionManager; private final PackageManagerInternal mPackageManagerInternal; private final AssociationStore mAssociationStore; private final SystemDataTransferRequestStore mSystemDataTransferRequestStore; private final ObservableUuidStore mObservableUuidStore; private final CompanionExemptionProcessor mCompanionExemptionProcessor; private final AssociationRequestsProcessor mAssociationRequestsProcessor; private final SystemDataTransferProcessor mSystemDataTransferProcessor; private final BackupRestoreProcessor mBackupRestoreProcessor; Loading @@ -156,12 +136,15 @@ public class CompanionDeviceManagerService extends SystemService { super(context); final ActivityManager activityManager = context.getSystemService(ActivityManager.class); mPowerExemptionManager = context.getSystemService(PowerExemptionManager.class); mAppOpsManager = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mAmInternal = LocalServices.getService(ActivityManagerInternal.class); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); final PowerExemptionManager powerExemptionManager = context.getSystemService( PowerExemptionManager.class); final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); final ActivityTaskManagerInternal atmInternal = LocalServices.getService( ActivityTaskManagerInternal.class); final ActivityManagerInternal amInternal = LocalServices.getService( ActivityManagerInternal.class); final PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); final UserManager userManager = context.getSystemService(UserManager.class); final PowerManagerInternal powerManagerInternal = LocalServices.getService( PowerManagerInternal.class); Loading @@ -173,25 +156,29 @@ public class CompanionDeviceManagerService extends SystemService { // Init processors mAssociationRequestsProcessor = new AssociationRequestsProcessor(context, mPackageManagerInternal, mAssociationStore); mBackupRestoreProcessor = new BackupRestoreProcessor(context, mPackageManagerInternal, packageManagerInternal, mAssociationStore); mBackupRestoreProcessor = new BackupRestoreProcessor(context, packageManagerInternal, mAssociationStore, associationDiskStore, mSystemDataTransferRequestStore, mAssociationRequestsProcessor); mCompanionAppBinder = new CompanionAppBinder(context); mCompanionExemptionProcessor = new CompanionExemptionProcessor(context, powerExemptionManager, appOpsManager, packageManagerInternal, atmInternal, amInternal, mAssociationStore); mDevicePresenceProcessor = new DevicePresenceProcessor(context, mCompanionAppBinder, userManager, mAssociationStore, mObservableUuidStore, powerManagerInternal); powerManagerInternal, mCompanionExemptionProcessor); mTransportManager = new CompanionTransportManager(context, mAssociationStore); mDisassociationProcessor = new DisassociationProcessor(context, activityManager, mAssociationStore, mPackageManagerInternal, mDevicePresenceProcessor, mAssociationStore, packageManagerInternal, mDevicePresenceProcessor, mCompanionAppBinder, mSystemDataTransferRequestStore, mTransportManager); mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mPackageManagerInternal, mAssociationStore, packageManagerInternal, mAssociationStore, mSystemDataTransferRequestStore, mTransportManager); // TODO(b/279663946): move context sync to a dedicated system service Loading @@ -202,7 +189,6 @@ public class CompanionDeviceManagerService extends SystemService { public void onStart() { // Init association stores mAssociationStore.refreshCache(); mAssociationStore.registerLocalListener(mAssociationStoreChangeListener); // Init UUID store mObservableUuidStore.getObservableUuidsForUser(getContext().getUserId()); Loading Loading @@ -240,11 +226,11 @@ public class CompanionDeviceManagerService extends SystemService { if (associations.isEmpty()) return; updateAtm(userId, associations); mCompanionExemptionProcessor.updateAtm(userId, associations); BackgroundThread.getHandler().sendMessageDelayed( obtainMessage(CompanionDeviceManagerService::maybeGrantAutoRevokeExemptions, this), MINUTES.toMillis(10)); try (ExecutorService executor = Executors.newSingleThreadExecutor()) { executor.execute(mCompanionExemptionProcessor::updateAutoRevokeExemptions); } } @Override Loading @@ -262,30 +248,30 @@ public class CompanionDeviceManagerService extends SystemService { if (!associationsForPackage.isEmpty()) { Slog.i(TAG, "Package removed or data cleared for user=[" + userId + "], package=[" + packageName + "]. Cleaning up CDM data..."); } for (AssociationInfo association : associationsForPackage) { mDisassociationProcessor.disassociate(association.getId()); } mCompanionAppBinder.onPackagesChanged(userId, packageName); } // Clear observable UUIDs for the package. final List<ObservableUuid> uuidsTobeObserved = mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); for (ObservableUuid uuid : uuidsTobeObserved) { mObservableUuidStore.removeObservableUuid(userId, uuid.getUuid(), packageName); } mCompanionAppBinder.onPackagesChanged(userId); } private void onPackageModifiedInternal(@UserIdInt int userId, @NonNull String packageName) { final List<AssociationInfo> associationsForPackage = final List<AssociationInfo> associations = mAssociationStore.getAssociationsByPackage(userId, packageName); for (AssociationInfo association : associationsForPackage) { updateSpecialAccessPermissionForAssociatedPackage(association.getUserId(), association.getPackageName()); } if (!associations.isEmpty()) { mCompanionExemptionProcessor.exemptPackage(userId, packageName, false); mCompanionAppBinder.onPackagesChanged(userId); mCompanionAppBinder.onPackagesChanged(userId, packageName); } } private void onPackageAddedInternal(@UserIdInt int userId, @NonNull String packageName) { Loading Loading @@ -765,130 +751,6 @@ public class CompanionDeviceManagerService extends SystemService { } } /** * Update special access for the association's package */ public void updateSpecialAccessPermissionForAssociatedPackage(int userId, String packageName) { final PackageInfo packageInfo = getPackageInfo(getContext(), userId, packageName); Binder.withCleanCallingIdentity(() -> updateSpecialAccessPermissionAsSystem(packageInfo)); } private void updateSpecialAccessPermissionAsSystem(PackageInfo packageInfo) { if (packageInfo == null) { return; } if (containsEither(packageInfo.requestedPermissions, android.Manifest.permission.RUN_IN_BACKGROUND, android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)) { mPowerExemptionManager.addToPermanentAllowList(packageInfo.packageName); } else { try { mPowerExemptionManager.removeFromPermanentAllowList(packageInfo.packageName); } catch (UnsupportedOperationException e) { Slog.w(TAG, packageInfo.packageName + " can't be removed from power save" + " whitelist. It might due to the package is whitelisted by the system."); } } NetworkPolicyManager networkPolicyManager = NetworkPolicyManager.from(getContext()); try { if (containsEither(packageInfo.requestedPermissions, android.Manifest.permission.USE_DATA_IN_BACKGROUND, android.Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)) { networkPolicyManager.addUidPolicy( packageInfo.applicationInfo.uid, NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND); } else { networkPolicyManager.removeUidPolicy( packageInfo.applicationInfo.uid, NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND); } } catch (IllegalArgumentException e) { Slog.e(TAG, e.getMessage()); } exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid); } private void exemptFromAutoRevoke(String packageName, int uid) { try { mAppOpsManager.setMode( AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid, packageName, AppOpsManager.MODE_IGNORED); } catch (RemoteException e) { Slog.w(TAG, "Error while granting auto revoke exemption for " + packageName, e); } } private void updateAtm(int userId, List<AssociationInfo> associations) { final Set<Integer> companionAppUids = new ArraySet<>(); for (AssociationInfo association : associations) { final int uid = mPackageManagerInternal.getPackageUid(association.getPackageName(), 0, userId); if (uid >= 0) { companionAppUids.add(uid); } } if (mAtmInternal != null) { mAtmInternal.setCompanionAppUids(userId, companionAppUids); } if (mAmInternal != null) { // Make a copy of the set and send it to ActivityManager. mAmInternal.setCompanionAppUids(userId, new ArraySet<>(companionAppUids)); } } private void maybeGrantAutoRevokeExemptions() { Slog.d(TAG, "maybeGrantAutoRevokeExemptions()"); PackageManager pm = getContext().getPackageManager(); for (int userId : LocalServices.getService(UserManagerInternal.class).getUserIds()) { SharedPreferences pref = getContext().getSharedPreferences( new File(Environment.getUserSystemDirectory(userId), PREF_FILE_NAME), Context.MODE_PRIVATE); if (pref.getBoolean(PREF_KEY_AUTO_REVOKE_GRANTS_DONE, false)) { continue; } try { final List<AssociationInfo> associations = mAssociationStore.getActiveAssociationsByUser(userId); for (AssociationInfo a : associations) { try { int uid = pm.getPackageUidAsUser(a.getPackageName(), userId); exemptFromAutoRevoke(a.getPackageName(), uid); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Unknown companion package: " + a.getPackageName(), e); } } } finally { pref.edit().putBoolean(PREF_KEY_AUTO_REVOKE_GRANTS_DONE, true).apply(); } } } private final AssociationStore.OnChangeListener mAssociationStoreChangeListener = new AssociationStore.OnChangeListener() { @Override public void onAssociationChanged(int changeType, AssociationInfo association) { Slog.d(TAG, "onAssociationChanged changeType=[" + changeType + "], association=[" + association); final int userId = association.getUserId(); final List<AssociationInfo> updatedAssociations = mAssociationStore.getActiveAssociationsByUser(userId); updateAtm(userId, updatedAssociations); updateSpecialAccessPermissionForAssociatedPackage(association.getUserId(), association.getPackageName()); } }; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onPackageRemoved(String packageName, int uid) { Loading @@ -911,10 +773,6 @@ public class CompanionDeviceManagerService extends SystemService { } }; private static <T> boolean containsEither(T[] array, T a, T b) { return ArrayUtils.contains(array, a) || ArrayUtils.contains(array, b); } private class LocalService implements CompanionDeviceManagerServiceInternal { @Override Loading
services/companion/java/com/android/server/companion/CompanionExemptionProcessor.java 0 → 100644 +219 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java +4 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,10 @@ public class CompanionAppBinder { /** * On package changed. */ public void onPackagesChanged(@UserIdInt int userId) { public void onPackagesChanged(@UserIdInt int userId, String packageName) { // TODO: We shouldn't need to clean up the whole user registry. We only need to remove the // package. I will do it in a separate change since it's not appropriate to use // PerUser anymore. mCompanionServicesRegister.invalidate(userId); } Loading
services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java +17 −10 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.CollectionUtils; import com.android.server.companion.CompanionExemptionProcessor; import com.android.server.companion.association.AssociationStore; import java.io.PrintWriter; Loading Loading @@ -101,6 +102,8 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene private final PowerManagerInternal mPowerManagerInternal; @NonNull private final UserManager mUserManager; @NonNull private final CompanionExemptionProcessor mCompanionExemptionProcessor; // NOTE: Same association may appear in more than one of the following sets at the same time. // (E.g. self-managed devices that have MAC addresses, could be reported as present by their Loading @@ -111,7 +114,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene @NonNull private final Set<Integer> mNearbyBleDevices = new HashSet<>(); @NonNull private final Set<Integer> mReportedSelfManagedDevices = new HashSet<>(); private final Set<Integer> mConnectedSelfManagedDevices = new HashSet<>(); @NonNull private final Set<ParcelUuid> mConnectedUuidDevices = new HashSet<>(); @NonNull Loading Loading @@ -146,7 +149,8 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene @NonNull UserManager userManager, @NonNull AssociationStore associationStore, @NonNull ObservableUuidStore observableUuidStore, @NonNull PowerManagerInternal powerManagerInternal) { @NonNull PowerManagerInternal powerManagerInternal, @NonNull CompanionExemptionProcessor companionExemptionProcessor) { mContext = context; mCompanionAppBinder = companionAppBinder; mAssociationStore = associationStore; Loading @@ -156,6 +160,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene mObservableUuidStore, this); mBleDeviceProcessor = new BleDeviceProcessor(associationStore, this); mPowerManagerInternal = powerManagerInternal; mCompanionExemptionProcessor = companionExemptionProcessor; } /** Initialize {@link DevicePresenceProcessor} */ Loading Loading @@ -404,7 +409,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * nearby (for "self-managed" associations). */ public boolean isDevicePresent(int associationId) { return mReportedSelfManagedDevices.contains(associationId) return mConnectedSelfManagedDevices.contains(associationId) || mConnectedBtDevices.contains(associationId) || mNearbyBleDevices.contains(associationId) || mSimulated.contains(associationId); Loading Loading @@ -451,7 +456,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * notifyDeviceAppeared()} */ public void onSelfManagedDeviceConnected(int associationId) { onDevicePresenceEvent(mReportedSelfManagedDevices, onDevicePresenceEvent(mConnectedSelfManagedDevices, associationId, EVENT_SELF_MANAGED_APPEARED); } Loading @@ -467,7 +472,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * notifyDeviceDisappeared()} */ public void onSelfManagedDeviceDisconnected(int associationId) { onDevicePresenceEvent(mReportedSelfManagedDevices, onDevicePresenceEvent(mConnectedSelfManagedDevices, associationId, EVENT_SELF_MANAGED_DISAPPEARED); } Loading @@ -475,7 +480,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene * Marks a "self-managed" device as disconnected when binderDied. */ public void onSelfManagedDeviceReporterBinderDied(int associationId) { onDevicePresenceEvent(mReportedSelfManagedDevices, onDevicePresenceEvent(mConnectedSelfManagedDevices, associationId, EVENT_SELF_MANAGED_DISAPPEARED); } Loading Loading @@ -683,6 +688,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene if (association.shouldBindWhenPresent()) { bindApplicationIfNeeded(userId, packageName, association.isSelfManaged()); mCompanionExemptionProcessor.exemptPackage(userId, packageName, true); } else { return; } Loading Loading @@ -715,6 +721,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene // Check if there are other devices associated to the app that are present. if (!shouldBindPackage(userId, packageName)) { mCompanionAppBinder.unbindCompanionApp(userId, packageName); mCompanionExemptionProcessor.exemptPackage(userId, packageName, false); } break; default: Loading Loading @@ -940,7 +947,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene mConnectedBtDevices.remove(id); mNearbyBleDevices.remove(id); mReportedSelfManagedDevices.remove(id); mConnectedSelfManagedDevices.remove(id); mSimulated.remove(id); synchronized (mBtDisconnectedDevices) { mBtDisconnectedDevices.remove(id); Loading Loading @@ -1100,7 +1107,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene out.append("Companion Device Present: "); if (mConnectedBtDevices.isEmpty() && mNearbyBleDevices.isEmpty() && mReportedSelfManagedDevices.isEmpty()) { && mConnectedSelfManagedDevices.isEmpty()) { out.append("<empty>\n"); return; } else { Loading Loading @@ -1130,11 +1137,11 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene } out.append(" Self-Reported Devices: "); if (mReportedSelfManagedDevices.isEmpty()) { if (mConnectedSelfManagedDevices.isEmpty()) { out.append("<empty>\n"); } else { out.append("\n"); for (int associationId : mReportedSelfManagedDevices) { for (int associationId : mConnectedSelfManagedDevices) { AssociationInfo a = mAssociationStore.getAssociationById(associationId); out.append(" ").append(a.toShortString()).append('\n'); } Loading