diff options
4 files changed, 267 insertions, 191 deletions
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 51034d24df14..384cf46f152c 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -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; @@ -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; @@ -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; @@ -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); @@ -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 @@ -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()); @@ -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 @@ -274,18 +260,16 @@ public class CompanionDeviceManagerService extends SystemService { mObservableUuidStore.removeObservableUuid(userId, uuid.getUuid(), packageName); } - mCompanionAppBinder.onPackagesChanged(userId); + mCompanionAppBinder.onPackagesChanged(userId, packageName); } 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, packageName); } - - mCompanionAppBinder.onPackagesChanged(userId); } private void onPackageAddedInternal(@UserIdInt int userId, @NonNull String packageName) { @@ -765,130 +749,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) { @@ -911,10 +771,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 diff --git a/services/companion/java/com/android/server/companion/CompanionExemptionProcessor.java b/services/companion/java/com/android/server/companion/CompanionExemptionProcessor.java new file mode 100644 index 000000000000..6ddb569f3a2f --- /dev/null +++ b/services/companion/java/com/android/server/companion/CompanionExemptionProcessor.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2024 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. + */ + +package com.android.server.companion; + +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.MODE_IGNORED; + +import static com.android.server.companion.utils.PackageUtils.getPackageInfo; + +import android.annotation.SuppressLint; +import android.app.ActivityManagerInternal; +import android.app.AppOpsManager; +import android.companion.AssociationInfo; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; +import android.net.NetworkPolicyManager; +import android.os.Binder; +import android.os.Environment; +import android.os.PowerExemptionManager; +import android.util.ArraySet; +import android.util.Slog; + +import com.android.internal.util.ArrayUtils; +import com.android.server.LocalServices; +import com.android.server.companion.association.AssociationStore; +import com.android.server.pm.UserManagerInternal; +import com.android.server.wm.ActivityTaskManagerInternal; + +import java.io.File; +import java.util.List; +import java.util.Set; + +@SuppressLint("LongLogTag") +public class CompanionExemptionProcessor { + + private static final String TAG = "CDM_CompanionExemptionProcessor"; + + 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 final Context mContext; + private final PowerExemptionManager mPowerExemptionManager; + private final AppOpsManager mAppOpsManager; + private final PackageManagerInternal mPackageManager; + private final ActivityTaskManagerInternal mAtmInternal; + private final ActivityManagerInternal mAmInternal; + private final AssociationStore mAssociationStore; + + public CompanionExemptionProcessor(Context context, PowerExemptionManager powerExemptionManager, + AppOpsManager appOpsManager, PackageManagerInternal packageManager, + ActivityTaskManagerInternal atmInternal, ActivityManagerInternal amInternal, + AssociationStore associationStore) { + mContext = context; + mPowerExemptionManager = powerExemptionManager; + mAppOpsManager = appOpsManager; + mPackageManager = packageManager; + mAtmInternal = atmInternal; + mAmInternal = amInternal; + mAssociationStore = associationStore; + + mAssociationStore.registerLocalListener(new AssociationStore.OnChangeListener() { + @Override + public void onAssociationChanged(int changeType, AssociationInfo association) { + final int userId = association.getUserId(); + final List<AssociationInfo> updatedAssociations = + mAssociationStore.getActiveAssociationsByUser(userId); + + updateAtm(userId, updatedAssociations); + } + }); + } + + /** + * Update ActivityManager and ActivityTaskManager exemptions + */ + public void updateAtm(int userId, List<AssociationInfo> associations) { + final Set<Integer> companionAppUids = new ArraySet<>(); + for (AssociationInfo association : associations) { + int uid = mPackageManager.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)); + } + } + + /** + * Update special access for the association's package + */ + public void exemptPackage(int userId, String packageName, boolean hasPresentDevices) { + final PackageInfo packageInfo = getPackageInfo(mContext, userId, packageName); + + Binder.withCleanCallingIdentity( + () -> exemptPackageAsSystem(userId, packageInfo, hasPresentDevices)); + } + + @SuppressLint("MissingPermission") + private void exemptPackageAsSystem(int userId, PackageInfo packageInfo, + boolean hasPresentDevices) { + if (packageInfo == null) { + return; + } + + // If the app has run-in-bg permission and present devices, add it to power saver allowlist. + if (containsEither(packageInfo.requestedPermissions, + android.Manifest.permission.RUN_IN_BACKGROUND, + android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND) + && hasPresentDevices) { + 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" + + " allowlist. It might be due to the package being allowlisted by the" + + " system."); + } + } + + // If the app has run-in-bg permission and present device, allow metered network use. + NetworkPolicyManager networkPolicyManager = NetworkPolicyManager.from(mContext); + try { + if (containsEither(packageInfo.requestedPermissions, + android.Manifest.permission.USE_DATA_IN_BACKGROUND, + android.Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND) + && hasPresentDevices) { + 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()); + } + + updateAutoRevokeExemption(packageInfo.packageName, packageInfo.applicationInfo.uid, + !mAssociationStore.getActiveAssociationsByPackage(userId, + packageInfo.packageName).isEmpty()); + } + + /** + * Update auto revoke exemptions. + * If the app has any association, exempt it from permission auto revoke. + */ + public void updateAutoRevokeExemptions() { + Slog.d(TAG, "maybeGrantAutoRevokeExemptions()"); + + PackageManager pm = mContext.getPackageManager(); + for (int userId : LocalServices.getService(UserManagerInternal.class).getUserIds()) { + SharedPreferences pref = mContext.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); + updateAutoRevokeExemption(a.getPackageName(), uid, true); + } 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(); + } + } + } + + @SuppressLint("MissingPermission") + private void updateAutoRevokeExemption(String packageName, int uid, boolean hasAssociations) { + try { + mAppOpsManager.setMode( + AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, + uid, + packageName, + hasAssociations ? MODE_IGNORED : MODE_ALLOWED); + } catch (Exception e) { + Slog.e(TAG, "Error while granting auto revoke exemption for " + packageName, e); + } + } + + private <T> boolean containsEither(T[] array, T a, T b) { + return ArrayUtils.contains(array, a) || ArrayUtils.contains(array, b); + } + +} diff --git a/services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java b/services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java index 60f46887fa5c..48accbf92e22 100644 --- a/services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java +++ b/services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java @@ -95,8 +95,8 @@ public class CompanionAppBinder { /** * On package changed. */ - public void onPackagesChanged(@UserIdInt int userId) { - mCompanionServicesRegister.invalidate(userId); + public void onPackagesChanged(@UserIdInt int userId, String packageName) { + mCompanionServicesRegister.forUser(userId).remove(packageName); } /** @@ -309,10 +309,6 @@ public class CompanionAppBinder { return forUser(userId).getOrDefault(packageName, Collections.emptyList()); } - synchronized void invalidate(@UserIdInt int userId) { - remove(userId); - } - @Override protected final @NonNull Map<String, List<ComponentName>> create(@UserIdInt int userId) { return PackageUtils.getCompanionServicesForUser(mContext, userId); diff --git a/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java b/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java index a374d279af0b..7b4dd7df8be3 100644 --- a/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java +++ b/services/companion/java/com/android/server/companion/devicepresence/DevicePresenceProcessor.java @@ -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; @@ -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 @@ -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 @@ -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; @@ -156,6 +160,7 @@ public class DevicePresenceProcessor implements AssociationStore.OnChangeListene mObservableUuidStore, this); mBleDeviceProcessor = new BleDeviceProcessor(associationStore, this); mPowerManagerInternal = powerManagerInternal; + mCompanionExemptionProcessor = companionExemptionProcessor; } /** Initialize {@link DevicePresenceProcessor} */ @@ -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); @@ -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); } @@ -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); } @@ -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); } @@ -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; } @@ -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: @@ -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); @@ -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 { @@ -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'); } |