Loading services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +0 −4 Original line number Diff line number Diff line Loading @@ -259,8 +259,6 @@ public class CompanionDeviceManagerService extends SystemService { for (AssociationInfo association : associationsForPackage) { mDisassociationProcessor.disassociate(association.getId(), REASON_PKG_DATA_CLEARED); } mCompanionAppBinder.onPackageChanged(userId); } // Clear observable UUIDs for the package. Loading @@ -276,8 +274,6 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationStore.getAssociationsByPackage(userId, packageName); if (!associations.isEmpty()) { mCompanionExemptionProcessor.exemptPackage(userId, packageName, false); mCompanionAppBinder.onPackageChanged(userId); } } Loading services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java +55 −34 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.companion.devicepresence; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; Loading @@ -25,14 +26,16 @@ import android.companion.CompanionDeviceService; import android.companion.DevicePresenceEvent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.Handler; import android.util.Pair; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.PerUser; import com.android.server.companion.CompanionDeviceManagerService; import com.android.server.companion.utils.PackageUtils; import java.io.PrintWriter; import java.util.ArrayList; Loading Loading @@ -70,12 +73,16 @@ import java.util.Set; public class CompanionAppBinder { private static final String TAG = "CDM_CompanionAppBinder"; private static final Intent COMPANION_SERVICE_INTENT = new Intent(CompanionDeviceService.SERVICE_INTERFACE); private static final String PROPERTY_PRIMARY_TAG = "android.companion.PROPERTY_PRIMARY_COMPANION_DEVICE_SERVICE"; private static final long REBIND_TIMEOUT = 10 * 1000; // 10 sec @NonNull private final Context mContext; @NonNull private final CompanionServicesRegister mCompanionServicesRegister; @NonNull @GuardedBy("mBoundCompanionApplications") Loading @@ -87,20 +94,10 @@ public class CompanionAppBinder { public CompanionAppBinder(@NonNull Context context) { mContext = context; mCompanionServicesRegister = new CompanionServicesRegister(); mBoundCompanionApplications = new HashMap<>(); mScheduledForRebindingCompanionApplications = new HashSet<>(); } /** * On package changed. */ public void onPackageChanged(@UserIdInt int userId) { // Note: To invalidate the user space for simplicity. We could alternatively manage each // package, but that would easily cause errors if one case is mis-handled. mCompanionServicesRegister.invalidate(userId); } /** * CDM binds to the companion app. */ Loading @@ -109,8 +106,9 @@ public class CompanionAppBinder { Slog.i(TAG, "Binding user=[" + userId + "], package=[" + packageName + "], isSelfManaged=[" + isSelfManaged + "]..."); final List<ComponentName> companionServices = mCompanionServicesRegister.forPackage(userId, packageName); final List<ComponentName> companionServices = getCompanionServiceComponentsForPackage( mContext, packageName, userId); if (companionServices.isEmpty()) { Slog.e(TAG, "Can not bind companion applications u" + userId + "/" + packageName + ": " + "eligible CompanionDeviceService not found.\n" Loading Loading @@ -299,28 +297,51 @@ public class CompanionAppBinder { return connectors != null ? connectors.get(0) : null; } private class CompanionServicesRegister extends PerUser<Map<String, List<ComponentName>>> { @Override @NonNull public synchronized Map<String, List<ComponentName>> forUser( @UserIdInt int userId) { return super.forUser(userId); /** * @return list of {@link CompanionDeviceService}-s per package for a given user. * Services marked as "primary" would always appear at the head of the lists, *before* * all non-primary services. */ private @NonNull List<ComponentName> getCompanionServiceComponentsForPackage( @NonNull Context context, @NonNull String packageName, @UserIdInt int userId) { final PackageManager pm = context.getPackageManager(); final List<ResolveInfo> companionServices = pm.queryIntentServicesAsUser( COMPANION_SERVICE_INTENT, PackageManager.ResolveInfoFlags.of(0), userId); final List<ComponentName> componentNames = new ArrayList<>(); for (ResolveInfo resolveInfo : companionServices) { final ServiceInfo service = resolveInfo.serviceInfo; final ComponentName componentName = service.getComponentName(); if (!componentName.getPackageName().equals(packageName)) continue; final boolean requiresPermission = Manifest.permission.BIND_COMPANION_DEVICE_SERVICE .equals(resolveInfo.serviceInfo.permission); if (!requiresPermission) { Slog.w(TAG, "CompanionDeviceService " + service.getComponentName().flattenToShortString() + " must require " + "android.permission.BIND_COMPANION_DEVICE_SERVICE"); break; } if (isPrimaryCompanionDeviceService(pm, componentName, userId)) { // "Primary" service should be at the head of the list. componentNames.add(0, componentName); } else { componentNames.add(componentName); } @NonNull synchronized List<ComponentName> forPackage( @UserIdInt int userId, @NonNull String packageName) { return forUser(userId).getOrDefault(packageName, Collections.emptyList()); } synchronized void invalidate(@UserIdInt int userId) { remove(userId); return componentNames; } @Override @NonNull protected final Map<String, List<ComponentName>> create(@UserIdInt int userId) { return PackageUtils.getCompanionServicesForUser(mContext, userId); private boolean isPrimaryCompanionDeviceService(@NonNull PackageManager pm, @NonNull ComponentName componentName, @UserIdInt int userId) { try { return pm.getPropertyAsUser(PROPERTY_PRIMARY_TAG, componentName.getPackageName(), componentName.getClassName(), userId).getBoolean(); } catch (PackageManager.NameNotFoundException e) { return false; } } } services/companion/java/com/android/server/companion/utils/PackageUtils.java +0 −71 Original line number Diff line number Diff line Loading @@ -26,25 +26,18 @@ import static com.android.internal.R.array.config_companionDevicePackages; import static com.android.internal.R.array.config_companionPermSyncEnabledCerts; import static com.android.internal.R.array.config_companionPermSyncEnabledPackages; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.ecm.EnhancedConfirmationManager; import android.companion.CompanionDeviceService; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManager.ResolveInfoFlags; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.os.Binder; import android.os.Process; Loading @@ -53,11 +46,7 @@ import android.util.Slog; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** Loading @@ -68,11 +57,6 @@ public final class PackageUtils { public static final int PACKAGE_NOT_FOUND = -1; private static final String TAG = "CDM_PackageUtils"; private static final Intent COMPANION_SERVICE_INTENT = new Intent(CompanionDeviceService.SERVICE_INTERFACE); private static final String PROPERTY_PRIMARY_TAG = "android.companion.PROPERTY_PRIMARY_COMPANION_DEVICE_SERVICE"; /** * Get package info */ Loading Loading @@ -120,61 +104,6 @@ public final class PackageUtils { + " in manifest to use this API"); } /** * @return list of {@link CompanionDeviceService}-s per package for a given user. * Services marked as "primary" would always appear at the head of the lists, *before* * all non-primary services. */ public static @NonNull Map<String, List<ComponentName>> getCompanionServicesForUser( @NonNull Context context, @UserIdInt int userId) { final PackageManager pm = context.getPackageManager(); final List<ResolveInfo> companionServices = pm.queryIntentServicesAsUser( COMPANION_SERVICE_INTENT, ResolveInfoFlags.of(0), userId); final Map<String, List<ComponentName>> packageNameToServiceInfoList = new HashMap<>(companionServices.size()); for (ResolveInfo resolveInfo : companionServices) { final ServiceInfo service = resolveInfo.serviceInfo; final boolean requiresPermission = Manifest.permission.BIND_COMPANION_DEVICE_SERVICE .equals(resolveInfo.serviceInfo.permission); if (!requiresPermission) { Slog.w(TAG, "CompanionDeviceService " + service.getComponentName().flattenToShortString() + " must require " + "android.permission.BIND_COMPANION_DEVICE_SERVICE"); continue; } // We'll need to prepend "primary" services, while appending the other (non-primary) // services to the list. final ArrayList<ComponentName> services = (ArrayList<ComponentName>) packageNameToServiceInfoList.computeIfAbsent( service.packageName, it -> new ArrayList<>(1)); final ComponentName componentName = service.getComponentName(); if (isPrimaryCompanionDeviceService(pm, componentName, userId)) { // "Primary" service should be at the head of the list. services.add(0, componentName); } else { services.add(componentName); } } return packageNameToServiceInfoList; } private static boolean isPrimaryCompanionDeviceService(@NonNull PackageManager pm, @NonNull ComponentName componentName, @UserIdInt int userId) { try { return pm.getPropertyAsUser(PROPERTY_PRIMARY_TAG, componentName.getPackageName(), componentName.getClassName(), userId).getBoolean(); } catch (PackageManager.NameNotFoundException e) { return false; } } /** * Check if the package is allowlisted in the overlay config. * For this we'll check to config arrays: Loading Loading
services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +0 −4 Original line number Diff line number Diff line Loading @@ -259,8 +259,6 @@ public class CompanionDeviceManagerService extends SystemService { for (AssociationInfo association : associationsForPackage) { mDisassociationProcessor.disassociate(association.getId(), REASON_PKG_DATA_CLEARED); } mCompanionAppBinder.onPackageChanged(userId); } // Clear observable UUIDs for the package. Loading @@ -276,8 +274,6 @@ public class CompanionDeviceManagerService extends SystemService { mAssociationStore.getAssociationsByPackage(userId, packageName); if (!associations.isEmpty()) { mCompanionExemptionProcessor.exemptPackage(userId, packageName, false); mCompanionAppBinder.onPackageChanged(userId); } } Loading
services/companion/java/com/android/server/companion/devicepresence/CompanionAppBinder.java +55 −34 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.companion.devicepresence; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; Loading @@ -25,14 +26,16 @@ import android.companion.CompanionDeviceService; import android.companion.DevicePresenceEvent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.Handler; import android.util.Pair; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.PerUser; import com.android.server.companion.CompanionDeviceManagerService; import com.android.server.companion.utils.PackageUtils; import java.io.PrintWriter; import java.util.ArrayList; Loading Loading @@ -70,12 +73,16 @@ import java.util.Set; public class CompanionAppBinder { private static final String TAG = "CDM_CompanionAppBinder"; private static final Intent COMPANION_SERVICE_INTENT = new Intent(CompanionDeviceService.SERVICE_INTERFACE); private static final String PROPERTY_PRIMARY_TAG = "android.companion.PROPERTY_PRIMARY_COMPANION_DEVICE_SERVICE"; private static final long REBIND_TIMEOUT = 10 * 1000; // 10 sec @NonNull private final Context mContext; @NonNull private final CompanionServicesRegister mCompanionServicesRegister; @NonNull @GuardedBy("mBoundCompanionApplications") Loading @@ -87,20 +94,10 @@ public class CompanionAppBinder { public CompanionAppBinder(@NonNull Context context) { mContext = context; mCompanionServicesRegister = new CompanionServicesRegister(); mBoundCompanionApplications = new HashMap<>(); mScheduledForRebindingCompanionApplications = new HashSet<>(); } /** * On package changed. */ public void onPackageChanged(@UserIdInt int userId) { // Note: To invalidate the user space for simplicity. We could alternatively manage each // package, but that would easily cause errors if one case is mis-handled. mCompanionServicesRegister.invalidate(userId); } /** * CDM binds to the companion app. */ Loading @@ -109,8 +106,9 @@ public class CompanionAppBinder { Slog.i(TAG, "Binding user=[" + userId + "], package=[" + packageName + "], isSelfManaged=[" + isSelfManaged + "]..."); final List<ComponentName> companionServices = mCompanionServicesRegister.forPackage(userId, packageName); final List<ComponentName> companionServices = getCompanionServiceComponentsForPackage( mContext, packageName, userId); if (companionServices.isEmpty()) { Slog.e(TAG, "Can not bind companion applications u" + userId + "/" + packageName + ": " + "eligible CompanionDeviceService not found.\n" Loading Loading @@ -299,28 +297,51 @@ public class CompanionAppBinder { return connectors != null ? connectors.get(0) : null; } private class CompanionServicesRegister extends PerUser<Map<String, List<ComponentName>>> { @Override @NonNull public synchronized Map<String, List<ComponentName>> forUser( @UserIdInt int userId) { return super.forUser(userId); /** * @return list of {@link CompanionDeviceService}-s per package for a given user. * Services marked as "primary" would always appear at the head of the lists, *before* * all non-primary services. */ private @NonNull List<ComponentName> getCompanionServiceComponentsForPackage( @NonNull Context context, @NonNull String packageName, @UserIdInt int userId) { final PackageManager pm = context.getPackageManager(); final List<ResolveInfo> companionServices = pm.queryIntentServicesAsUser( COMPANION_SERVICE_INTENT, PackageManager.ResolveInfoFlags.of(0), userId); final List<ComponentName> componentNames = new ArrayList<>(); for (ResolveInfo resolveInfo : companionServices) { final ServiceInfo service = resolveInfo.serviceInfo; final ComponentName componentName = service.getComponentName(); if (!componentName.getPackageName().equals(packageName)) continue; final boolean requiresPermission = Manifest.permission.BIND_COMPANION_DEVICE_SERVICE .equals(resolveInfo.serviceInfo.permission); if (!requiresPermission) { Slog.w(TAG, "CompanionDeviceService " + service.getComponentName().flattenToShortString() + " must require " + "android.permission.BIND_COMPANION_DEVICE_SERVICE"); break; } if (isPrimaryCompanionDeviceService(pm, componentName, userId)) { // "Primary" service should be at the head of the list. componentNames.add(0, componentName); } else { componentNames.add(componentName); } @NonNull synchronized List<ComponentName> forPackage( @UserIdInt int userId, @NonNull String packageName) { return forUser(userId).getOrDefault(packageName, Collections.emptyList()); } synchronized void invalidate(@UserIdInt int userId) { remove(userId); return componentNames; } @Override @NonNull protected final Map<String, List<ComponentName>> create(@UserIdInt int userId) { return PackageUtils.getCompanionServicesForUser(mContext, userId); private boolean isPrimaryCompanionDeviceService(@NonNull PackageManager pm, @NonNull ComponentName componentName, @UserIdInt int userId) { try { return pm.getPropertyAsUser(PROPERTY_PRIMARY_TAG, componentName.getPackageName(), componentName.getClassName(), userId).getBoolean(); } catch (PackageManager.NameNotFoundException e) { return false; } } }
services/companion/java/com/android/server/companion/utils/PackageUtils.java +0 −71 Original line number Diff line number Diff line Loading @@ -26,25 +26,18 @@ import static com.android.internal.R.array.config_companionDevicePackages; import static com.android.internal.R.array.config_companionPermSyncEnabledCerts; import static com.android.internal.R.array.config_companionPermSyncEnabledPackages; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.ecm.EnhancedConfirmationManager; import android.companion.CompanionDeviceService; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManager.ResolveInfoFlags; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.os.Binder; import android.os.Process; Loading @@ -53,11 +46,7 @@ import android.util.Slog; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** Loading @@ -68,11 +57,6 @@ public final class PackageUtils { public static final int PACKAGE_NOT_FOUND = -1; private static final String TAG = "CDM_PackageUtils"; private static final Intent COMPANION_SERVICE_INTENT = new Intent(CompanionDeviceService.SERVICE_INTERFACE); private static final String PROPERTY_PRIMARY_TAG = "android.companion.PROPERTY_PRIMARY_COMPANION_DEVICE_SERVICE"; /** * Get package info */ Loading Loading @@ -120,61 +104,6 @@ public final class PackageUtils { + " in manifest to use this API"); } /** * @return list of {@link CompanionDeviceService}-s per package for a given user. * Services marked as "primary" would always appear at the head of the lists, *before* * all non-primary services. */ public static @NonNull Map<String, List<ComponentName>> getCompanionServicesForUser( @NonNull Context context, @UserIdInt int userId) { final PackageManager pm = context.getPackageManager(); final List<ResolveInfo> companionServices = pm.queryIntentServicesAsUser( COMPANION_SERVICE_INTENT, ResolveInfoFlags.of(0), userId); final Map<String, List<ComponentName>> packageNameToServiceInfoList = new HashMap<>(companionServices.size()); for (ResolveInfo resolveInfo : companionServices) { final ServiceInfo service = resolveInfo.serviceInfo; final boolean requiresPermission = Manifest.permission.BIND_COMPANION_DEVICE_SERVICE .equals(resolveInfo.serviceInfo.permission); if (!requiresPermission) { Slog.w(TAG, "CompanionDeviceService " + service.getComponentName().flattenToShortString() + " must require " + "android.permission.BIND_COMPANION_DEVICE_SERVICE"); continue; } // We'll need to prepend "primary" services, while appending the other (non-primary) // services to the list. final ArrayList<ComponentName> services = (ArrayList<ComponentName>) packageNameToServiceInfoList.computeIfAbsent( service.packageName, it -> new ArrayList<>(1)); final ComponentName componentName = service.getComponentName(); if (isPrimaryCompanionDeviceService(pm, componentName, userId)) { // "Primary" service should be at the head of the list. services.add(0, componentName); } else { services.add(componentName); } } return packageNameToServiceInfoList; } private static boolean isPrimaryCompanionDeviceService(@NonNull PackageManager pm, @NonNull ComponentName componentName, @UserIdInt int userId) { try { return pm.getPropertyAsUser(PROPERTY_PRIMARY_TAG, componentName.getPackageName(), componentName.getClassName(), userId).getBoolean(); } catch (PackageManager.NameNotFoundException e) { return false; } } /** * Check if the package is allowlisted in the overlay config. * For this we'll check to config arrays: Loading