Loading services/core/java/com/android/server/appbinding/AppBindingService.java +109 −29 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; import android.os.Handler; import android.os.IInterface; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; Loading @@ -48,11 +47,13 @@ import com.android.server.SystemService; import com.android.server.appbinding.finders.AppServiceFinder; import com.android.server.appbinding.finders.CarrierMessagingClientServiceFinder; import com.android.server.appbinding.finders.SupervisionAppServiceFinder; import com.android.server.utils.Slogf; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Consumer; /** Loading Loading @@ -143,8 +144,8 @@ public class AppBindingService extends Binder { } /** Get the list of services bound to a specific finder class. */ public <T extends IInterface> List<AppServiceConnection> getAppServiceConnections( Class<? extends AppServiceFinder<?, T>> appServiceFinderClass, int userId) { public List<AppServiceConnection> getAppServiceConnections( Class<? extends AppServiceFinder<?, ?>> appServiceFinderClass, int userId) { List<AppServiceConnection> serviceConnections = new ArrayList<>(); synchronized (mLock) { for (int i = 0; i < mApps.size(); i++) { Loading @@ -152,10 +153,7 @@ public class AppBindingService extends Binder { if (app.getClass() != appServiceFinderClass) { continue; } AppServiceConnection conn = getBoundConnectionLocked(userId, app); if (conn != null) { serviceConnections.add(conn); } serviceConnections.addAll(getBoundConnectionsLocked(userId, app)); } } return serviceConnections; Loading @@ -163,23 +161,33 @@ public class AppBindingService extends Binder { /** Get the connection bound to a specific finder. If the connection does not * already exist, create one. */ private AppServiceConnection getBoundConnectionLocked(int userId, AppServiceFinder app) { AppServiceConnection conn = findConnectionLock(userId, app); private List<AppServiceConnection> getBoundConnectionsLocked(int userId, AppServiceFinder app) { Set<String> targetPackages = app.getTargetPackages(userId); List<AppServiceConnection> connections = new ArrayList<>(); for (String targetPackage : targetPackages) { AppServiceConnection conn = findConnectionLock(userId, app, targetPackage); if (conn == null) { final ServiceInfo service = app.findService(userId, mIPackageManager, mConstants); if (service==null) { Slog.d(TAG, "Can't create connection with app " + app.getTargetPackage(userId) + ". Service is null."); return null; } conn = new AppServiceConnection( mContext, userId, mConstants, mHandler, app, service.getComponentName()); } final ServiceInfo service = app.findService(userId, mIPackageManager, mConstants, targetPackage); if (service != null) { conn = new AppServiceConnection( mContext, userId, mConstants, mHandler, app, targetPackage, service.getComponentName()); mConnections.add(conn); conn.bind(); return conn; } } if (conn != null) { connections.add(conn); } } return connections; } private AppBindingService(Injector injector, Context context) { Loading Loading @@ -249,6 +257,8 @@ public class AppBindingService extends Binder { final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); packageFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); packageFilter.addDataScheme("package"); mContext.registerReceiverAsUser(mPackageUserMonitor, UserHandle.ALL, Loading Loading @@ -329,6 +339,12 @@ public class AppBindingService extends Binder { case Intent.ACTION_PACKAGE_CHANGED: handlePackageAddedReplacing(packageName, userId); break; case Intent.ACTION_PACKAGE_REMOVED: case Intent.ACTION_PACKAGE_FULLY_REMOVED: if (!replacing) { onAppRemoved(userId, packageName); } break; } } }; Loading Loading @@ -386,6 +402,22 @@ public class AppBindingService extends Binder { } } private void onAppRemoved(int userId, String packageName) { if (!Flags.enableSupervisionAppService()) { return; } if (DEBUG) { Slogf.d(TAG, "onAppRemoved: u%s %s", userId, packageName); } synchronized (mLock) { final AppServiceFinder finder = findFinderLocked(userId, packageName); if (finder != null) { bindServicesLocked(userId, finder, "package removed"); } } } /** * Called when a target package changes; e.g. when the user changes the default SMS app. */ Loading @@ -405,16 +437,21 @@ public class AppBindingService extends Binder { private AppServiceFinder findFinderLocked(int userId, @NonNull String packageName) { for (int i = 0; i < mApps.size(); i++) { final AppServiceFinder app = mApps.get(i); if (Flags.enableSupervisionAppService()) { if (app.getTargetPackages(userId).contains(packageName)) { return app; } } else { if (packageName.equals(app.getTargetPackage(userId))) { return app; } } } return null; } @Nullable private AppServiceConnection findConnectionLock( int userId, @NonNull AppServiceFinder target) { private AppServiceConnection findConnectionLock(int userId, @NonNull AppServiceFinder target) { for (int i = 0; i < mConnections.size(); i++) { final AppServiceConnection conn = mConnections.get(i); if ((conn.getUserId() == userId) && (conn.getFinder() == target)) { Loading @@ -424,6 +461,20 @@ public class AppBindingService extends Binder { return null; } @Nullable private AppServiceConnection findConnectionLock( int userId, @NonNull AppServiceFinder target, String targetPackage) { for (int i = 0; i < mConnections.size(); i++) { final AppServiceConnection conn = mConnections.get(i); if ((conn.getUserId() == userId) && (conn.getFinder() == target) && conn.getPackageName().equals(targetPackage)) { return conn; } } return null; } private void handlePackageAddedReplacing(String packageName, int userId) { if (DEBUG) { Slog.d(TAG, "handlePackageAddedReplacing: u" + userId + " " + packageName); Loading Loading @@ -456,7 +507,37 @@ public class AppBindingService extends Binder { if (target != null && target != app) { continue; } if (!Flags.enableSupervisionAppService()) { bindServicesForFinderLocked(userId, target, reasonForLog, app); // old code continue; } // Disconnect from existing binding. unbindServicesLocked(userId, app, reasonForLog); final List<ServiceInfo> services = app.findServices(userId, mIPackageManager, mConstants); if (services==null || services.isEmpty()) { continue; } for (ServiceInfo service : services) { if (DEBUG) { Slog.d(TAG, "bindServicesLocked: u" + userId + " " + app.getAppDescription() + " binding " + service.getComponentName() + " for " + reasonForLog); } if (service == null) { continue; } final AppServiceConnection conn = new AppServiceConnection(mContext, userId, mConstants, mHandler, app, service.packageName, service.getComponentName()); mConnections.add(conn); conn.bind(); } } } private void bindServicesForFinderLocked(int userId, @Nullable AppServiceFinder target, @NonNull String reasonForLog, AppServiceFinder app) { // Disconnect from existing binding. final AppServiceConnection existingConn = findConnectionLock(userId, app); if (existingConn != null) { Loading @@ -465,7 +546,7 @@ public class AppBindingService extends Binder { final ServiceInfo service = app.findService(userId, mIPackageManager, mConstants); if (service == null) { continue; return; } if (DEBUG) { Slog.d(TAG, "bindServicesLocked: u" + userId + " " + app.getAppDescription() Loading @@ -473,11 +554,10 @@ public class AppBindingService extends Binder { } final AppServiceConnection conn = new AppServiceConnection(mContext, userId, mConstants, mHandler, app, service.getComponentName()); app, service.packageName, service.getComponentName()); mConnections.add(conn); conn.bind(); } } private void unbindServicesLocked(int userId, @Nullable AppServiceFinder target, @NonNull String reasonForLog) { Loading services/core/java/com/android/server/appbinding/AppServiceConnection.java +9 −3 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { public static final String TAG = "AppServiceConnection"; private final AppBindingConstants mConstants; private final AppServiceFinder mFinder; private final String mPackageName; /** * Listener for connection status updates Loading @@ -54,7 +55,7 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { new CopyOnWriteArrayList<>(); AppServiceConnection(Context context, int userId, AppBindingConstants constants, Handler handler, AppServiceFinder finder, Handler handler, AppServiceFinder finder, String packageName, @NonNull ComponentName componentName) { super(TAG, context, handler, userId, componentName, constants.SERVICE_RECONNECT_BACKOFF_SEC, Loading @@ -63,6 +64,7 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { constants.SERVICE_STABLE_CONNECTION_THRESHOLD_SEC); mFinder = finder; mConstants = constants; mPackageName = packageName; } @Override Loading @@ -76,8 +78,8 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { if (service != null) { // Notify all listeners. Slogf.d(TAG, "Service for %s is connected. Notifying listeners.", getComponentName()); Slogf.d(TAG, "Service for %s is connected. Notifying %s listeners.", getComponentName(), mConnectionListeners.size()); for (ConnectionStatusListener listener : mConnectionListeners) { listener.onConnected(this, service); } Loading @@ -91,6 +93,10 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { return mFinder; } public String getPackageName() { return mPackageName; } /** * Adds a listener to be notified of connection changes. * If service is already connected, notify immediately. Loading services/core/java/com/android/server/appbinding/finders/AppServiceFinder.java +156 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.appbinding.finders; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.supervision.flags.Flags; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.ServiceInfo; Loading @@ -34,6 +35,11 @@ import com.android.server.appbinding.AppBindingService; import com.android.server.appbinding.AppBindingUtils; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; /** Loading @@ -53,14 +59,37 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten private final Object mLock = new Object(); @GuardedBy("mLock") @Deprecated private final SparseArray<String> mTargetPackages = new SparseArray(4); @GuardedBy("mLock") @Deprecated private final SparseArray<ServiceInfo> mTargetServices = new SparseArray(4); @GuardedBy("mLock") @Deprecated private final SparseArray<String> mLastMessages = new SparseArray(4); @GuardedBy("mLock") private final SparseArray<HashMap<String, TargetServiceInfo>> mServiceInfos = new SparseArray(4); /** * Helper class to store the ServiceInfo and the last message related to it. */ private static class TargetServiceInfo { @Nullable public final ServiceInfo serviceInfo; @Nullable public final String lastMessage; TargetServiceInfo(@Nullable ServiceInfo serviceInfo, @Nullable String lastMessage) { this.serviceInfo = serviceInfo; this.lastMessage = lastMessage; } } public AppServiceFinder(Context context, BiConsumer<AppServiceFinder, Integer> listener, Handler callbackHandler) { Loading Loading @@ -88,6 +117,7 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten mTargetPackages.delete(userId); mTargetServices.delete(userId); mLastMessages.delete(userId); mServiceInfos.delete(userId); } } Loading @@ -95,6 +125,7 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten * Find the target service from the target app on a given user. */ @Nullable @Deprecated public final ServiceInfo findService(int userId, IPackageManager ipm, AppBindingConstants constants) { synchronized (mLock) { Loading Loading @@ -155,6 +186,90 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten } } /** * Find the target service from the target app on a given user. */ @Nullable public final ServiceInfo findService(int userId, IPackageManager ipm, AppBindingConstants constants, String targetPackage) { synchronized (mLock) { HashMap<String, TargetServiceInfo> currServiceInfo = mServiceInfos.get(userId); if (DEBUG) { Slog.d(TAG, getAppDescription() + " package=" + targetPackage); } if (!isEnabled(constants, userId)) { final String message = "feature disabled"; currServiceInfo.put(targetPackage, new TargetServiceInfo(null, message)); Slog.i(TAG, getAppDescription() + " " + message); return null; } final StringBuilder errorMessage = new StringBuilder(); final ServiceInfo service = AppBindingUtils.findService( targetPackage, userId, getServiceAction(), getServicePermission(), getServiceClass(), ipm, errorMessage); if (service == null) { final String message = errorMessage.toString(); currServiceInfo.put(targetPackage, new TargetServiceInfo(null, message)); if (DEBUG) { Slog.w(TAG, getAppDescription() + " package " + targetPackage + " u" + userId + " " + message); } return null; } final String error = validateService(service); if (error != null) { currServiceInfo.put(targetPackage, new TargetServiceInfo(null, error)); Log.e(TAG, error); return null; } currServiceInfo.put(targetPackage, new TargetServiceInfo(service, "Valid service found")); return service; } } /** * Find the list of target service from the target apps on a given user. */ @Nullable public final List<ServiceInfo> findServices(int userId, IPackageManager ipm, AppBindingConstants constants) { final Set<String> targetPackages = getTargetPackages(userId); synchronized (mLock) { mServiceInfos.put(userId, new HashMap<String, TargetServiceInfo>()); if (DEBUG) { Slog.d(TAG, getAppDescription() + " packages=" + targetPackages); } if (!isEnabled(constants, userId) || targetPackages.isEmpty()) { final String message = (!isEnabled(constants, userId)) ? "feature disabled" : "Target packages not found"; mServiceInfos.get(userId).put(null, new TargetServiceInfo(null, message)); Slog.w(TAG, getAppDescription() + " u" + userId + " " + message); return new ArrayList<>(); } } List<ServiceInfo> services = new ArrayList<>(); for (String targetPackage: targetPackages) { ServiceInfo service = findService(userId, ipm, constants, targetPackage); if (service != null) { services.add(service); } } return services; } protected abstract Class<TServiceType> getServiceClass(); /** Loading @@ -166,8 +281,14 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten * @return the target package on a given user. */ @Nullable @Deprecated public abstract String getTargetPackage(int userId); /** * @return the target packages on a given user. */ public abstract Set<String> getTargetPackages(int userId); /** * @return the intent action that identifies the target service in the target app. */ Loading Loading @@ -199,6 +320,31 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten pw.println(); synchronized (mLock) { for (int i = 0; i < mServiceInfos.size(); i++) { final int userId = mServiceInfos.keyAt(i); pw.print(prefix); pw.print(" User: "); pw.print(userId); pw.println(); for (String targetPackage : mServiceInfos.get(userId).keySet()) { pw.print(prefix); pw.print(" Package: "); pw.print(targetPackage); pw.println(); pw.print(prefix); pw.print(" Service: "); pw.print(mServiceInfos.get(userId).get(targetPackage).serviceInfo); pw.println(); pw.print(prefix); pw.print(" Message: "); pw.print(mServiceInfos.get(userId).get(targetPackage).lastMessage); pw.println(); } pw.println(); } for (int i = 0; i < mTargetPackages.size(); i++) { final int userId = mTargetPackages.keyAt(i); pw.print(prefix); Loading Loading @@ -227,6 +373,16 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten /** Dumpys support */ public void dumpSimple(PrintWriter pw) { synchronized (mLock) { for (int i = 0; i < mServiceInfos.size(); i++) { final int userId = mServiceInfos.keyAt(i); pw.println(String.format("finder,%s,%s", getAppDescription(), userId)); for (String targetPackage : mServiceInfos.get(userId).keySet()) { pw.println(String.format("finder,%s,%s,%s,%s,%s", getAppDescription(), userId, targetPackage, mServiceInfos.get(userId).get(targetPackage).serviceInfo, mServiceInfos.get(userId).get(targetPackage).lastMessage)); } } for (int i = 0; i < mTargetPackages.size(); i++) { final int userId = mTargetPackages.keyAt(i); pw.print("finder,"); Loading services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java +19 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,9 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.util.CollectionUtils; import com.android.server.appbinding.AppBindingConstants; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; /** Loading Loading @@ -85,6 +88,7 @@ public class CarrierMessagingClientServiceFinder } @Override @Deprecated public String getTargetPackage(int userId) { final String ret = CollectionUtils.firstOrNull(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SMS, UserHandle.of(userId))); Loading @@ -96,6 +100,21 @@ public class CarrierMessagingClientServiceFinder return ret; } @Override public Set<String> getTargetPackages(int userId) { String targetPackage = CollectionUtils.firstOrNull(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SMS, UserHandle.of(userId))); if (DEBUG) { Slog.d(TAG, "getTargetPackages()=" + targetPackage); } if (targetPackage == null) { return Collections.emptySet(); } return new HashSet<>(Collections.singletonList(targetPackage)); } @Override public void startMonitoring() { mRoleManager.addOnRoleHoldersChangedListenerAsUser( Loading services/core/java/com/android/server/appbinding/finders/SupervisionAppServiceFinder.java +13 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.appbinding.AppBindingConstants; import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; /** Finds the @{link SupervisionAppService} implementation within the supervision app. */ Loading Loading @@ -77,6 +79,7 @@ public class SupervisionAppServiceFinder @Nullable @Override @Deprecated public String getTargetPackage(int userId) { final String ret = CollectionUtils.firstOrNull( Loading @@ -85,6 +88,16 @@ public class SupervisionAppServiceFinder return ret; } @Override public Set<String> getTargetPackages(int userId) { final Set<String> ret = new HashSet<>(); ret.addAll(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SYSTEM_SUPERVISION, UserHandle.of(userId))); ret.addAll(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SUPERVISION, UserHandle.of(userId))); return ret; } @NonNull @Override protected String getServiceAction() { Loading Loading
services/core/java/com/android/server/appbinding/AppBindingService.java +109 −29 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; import android.os.Handler; import android.os.IInterface; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; Loading @@ -48,11 +47,13 @@ import com.android.server.SystemService; import com.android.server.appbinding.finders.AppServiceFinder; import com.android.server.appbinding.finders.CarrierMessagingClientServiceFinder; import com.android.server.appbinding.finders.SupervisionAppServiceFinder; import com.android.server.utils.Slogf; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Consumer; /** Loading Loading @@ -143,8 +144,8 @@ public class AppBindingService extends Binder { } /** Get the list of services bound to a specific finder class. */ public <T extends IInterface> List<AppServiceConnection> getAppServiceConnections( Class<? extends AppServiceFinder<?, T>> appServiceFinderClass, int userId) { public List<AppServiceConnection> getAppServiceConnections( Class<? extends AppServiceFinder<?, ?>> appServiceFinderClass, int userId) { List<AppServiceConnection> serviceConnections = new ArrayList<>(); synchronized (mLock) { for (int i = 0; i < mApps.size(); i++) { Loading @@ -152,10 +153,7 @@ public class AppBindingService extends Binder { if (app.getClass() != appServiceFinderClass) { continue; } AppServiceConnection conn = getBoundConnectionLocked(userId, app); if (conn != null) { serviceConnections.add(conn); } serviceConnections.addAll(getBoundConnectionsLocked(userId, app)); } } return serviceConnections; Loading @@ -163,23 +161,33 @@ public class AppBindingService extends Binder { /** Get the connection bound to a specific finder. If the connection does not * already exist, create one. */ private AppServiceConnection getBoundConnectionLocked(int userId, AppServiceFinder app) { AppServiceConnection conn = findConnectionLock(userId, app); private List<AppServiceConnection> getBoundConnectionsLocked(int userId, AppServiceFinder app) { Set<String> targetPackages = app.getTargetPackages(userId); List<AppServiceConnection> connections = new ArrayList<>(); for (String targetPackage : targetPackages) { AppServiceConnection conn = findConnectionLock(userId, app, targetPackage); if (conn == null) { final ServiceInfo service = app.findService(userId, mIPackageManager, mConstants); if (service==null) { Slog.d(TAG, "Can't create connection with app " + app.getTargetPackage(userId) + ". Service is null."); return null; } conn = new AppServiceConnection( mContext, userId, mConstants, mHandler, app, service.getComponentName()); } final ServiceInfo service = app.findService(userId, mIPackageManager, mConstants, targetPackage); if (service != null) { conn = new AppServiceConnection( mContext, userId, mConstants, mHandler, app, targetPackage, service.getComponentName()); mConnections.add(conn); conn.bind(); return conn; } } if (conn != null) { connections.add(conn); } } return connections; } private AppBindingService(Injector injector, Context context) { Loading Loading @@ -249,6 +257,8 @@ public class AppBindingService extends Binder { final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); packageFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); packageFilter.addDataScheme("package"); mContext.registerReceiverAsUser(mPackageUserMonitor, UserHandle.ALL, Loading Loading @@ -329,6 +339,12 @@ public class AppBindingService extends Binder { case Intent.ACTION_PACKAGE_CHANGED: handlePackageAddedReplacing(packageName, userId); break; case Intent.ACTION_PACKAGE_REMOVED: case Intent.ACTION_PACKAGE_FULLY_REMOVED: if (!replacing) { onAppRemoved(userId, packageName); } break; } } }; Loading Loading @@ -386,6 +402,22 @@ public class AppBindingService extends Binder { } } private void onAppRemoved(int userId, String packageName) { if (!Flags.enableSupervisionAppService()) { return; } if (DEBUG) { Slogf.d(TAG, "onAppRemoved: u%s %s", userId, packageName); } synchronized (mLock) { final AppServiceFinder finder = findFinderLocked(userId, packageName); if (finder != null) { bindServicesLocked(userId, finder, "package removed"); } } } /** * Called when a target package changes; e.g. when the user changes the default SMS app. */ Loading @@ -405,16 +437,21 @@ public class AppBindingService extends Binder { private AppServiceFinder findFinderLocked(int userId, @NonNull String packageName) { for (int i = 0; i < mApps.size(); i++) { final AppServiceFinder app = mApps.get(i); if (Flags.enableSupervisionAppService()) { if (app.getTargetPackages(userId).contains(packageName)) { return app; } } else { if (packageName.equals(app.getTargetPackage(userId))) { return app; } } } return null; } @Nullable private AppServiceConnection findConnectionLock( int userId, @NonNull AppServiceFinder target) { private AppServiceConnection findConnectionLock(int userId, @NonNull AppServiceFinder target) { for (int i = 0; i < mConnections.size(); i++) { final AppServiceConnection conn = mConnections.get(i); if ((conn.getUserId() == userId) && (conn.getFinder() == target)) { Loading @@ -424,6 +461,20 @@ public class AppBindingService extends Binder { return null; } @Nullable private AppServiceConnection findConnectionLock( int userId, @NonNull AppServiceFinder target, String targetPackage) { for (int i = 0; i < mConnections.size(); i++) { final AppServiceConnection conn = mConnections.get(i); if ((conn.getUserId() == userId) && (conn.getFinder() == target) && conn.getPackageName().equals(targetPackage)) { return conn; } } return null; } private void handlePackageAddedReplacing(String packageName, int userId) { if (DEBUG) { Slog.d(TAG, "handlePackageAddedReplacing: u" + userId + " " + packageName); Loading Loading @@ -456,7 +507,37 @@ public class AppBindingService extends Binder { if (target != null && target != app) { continue; } if (!Flags.enableSupervisionAppService()) { bindServicesForFinderLocked(userId, target, reasonForLog, app); // old code continue; } // Disconnect from existing binding. unbindServicesLocked(userId, app, reasonForLog); final List<ServiceInfo> services = app.findServices(userId, mIPackageManager, mConstants); if (services==null || services.isEmpty()) { continue; } for (ServiceInfo service : services) { if (DEBUG) { Slog.d(TAG, "bindServicesLocked: u" + userId + " " + app.getAppDescription() + " binding " + service.getComponentName() + " for " + reasonForLog); } if (service == null) { continue; } final AppServiceConnection conn = new AppServiceConnection(mContext, userId, mConstants, mHandler, app, service.packageName, service.getComponentName()); mConnections.add(conn); conn.bind(); } } } private void bindServicesForFinderLocked(int userId, @Nullable AppServiceFinder target, @NonNull String reasonForLog, AppServiceFinder app) { // Disconnect from existing binding. final AppServiceConnection existingConn = findConnectionLock(userId, app); if (existingConn != null) { Loading @@ -465,7 +546,7 @@ public class AppBindingService extends Binder { final ServiceInfo service = app.findService(userId, mIPackageManager, mConstants); if (service == null) { continue; return; } if (DEBUG) { Slog.d(TAG, "bindServicesLocked: u" + userId + " " + app.getAppDescription() Loading @@ -473,11 +554,10 @@ public class AppBindingService extends Binder { } final AppServiceConnection conn = new AppServiceConnection(mContext, userId, mConstants, mHandler, app, service.getComponentName()); app, service.packageName, service.getComponentName()); mConnections.add(conn); conn.bind(); } } private void unbindServicesLocked(int userId, @Nullable AppServiceFinder target, @NonNull String reasonForLog) { Loading
services/core/java/com/android/server/appbinding/AppServiceConnection.java +9 −3 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { public static final String TAG = "AppServiceConnection"; private final AppBindingConstants mConstants; private final AppServiceFinder mFinder; private final String mPackageName; /** * Listener for connection status updates Loading @@ -54,7 +55,7 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { new CopyOnWriteArrayList<>(); AppServiceConnection(Context context, int userId, AppBindingConstants constants, Handler handler, AppServiceFinder finder, Handler handler, AppServiceFinder finder, String packageName, @NonNull ComponentName componentName) { super(TAG, context, handler, userId, componentName, constants.SERVICE_RECONNECT_BACKOFF_SEC, Loading @@ -63,6 +64,7 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { constants.SERVICE_STABLE_CONNECTION_THRESHOLD_SEC); mFinder = finder; mConstants = constants; mPackageName = packageName; } @Override Loading @@ -76,8 +78,8 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { if (service != null) { // Notify all listeners. Slogf.d(TAG, "Service for %s is connected. Notifying listeners.", getComponentName()); Slogf.d(TAG, "Service for %s is connected. Notifying %s listeners.", getComponentName(), mConnectionListeners.size()); for (ConnectionStatusListener listener : mConnectionListeners) { listener.onConnected(this, service); } Loading @@ -91,6 +93,10 @@ public class AppServiceConnection extends PersistentConnection<IInterface> { return mFinder; } public String getPackageName() { return mPackageName; } /** * Adds a listener to be notified of connection changes. * If service is already connected, notify immediately. Loading
services/core/java/com/android/server/appbinding/finders/AppServiceFinder.java +156 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.appbinding.finders; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.supervision.flags.Flags; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.ServiceInfo; Loading @@ -34,6 +35,11 @@ import com.android.server.appbinding.AppBindingService; import com.android.server.appbinding.AppBindingUtils; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; /** Loading @@ -53,14 +59,37 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten private final Object mLock = new Object(); @GuardedBy("mLock") @Deprecated private final SparseArray<String> mTargetPackages = new SparseArray(4); @GuardedBy("mLock") @Deprecated private final SparseArray<ServiceInfo> mTargetServices = new SparseArray(4); @GuardedBy("mLock") @Deprecated private final SparseArray<String> mLastMessages = new SparseArray(4); @GuardedBy("mLock") private final SparseArray<HashMap<String, TargetServiceInfo>> mServiceInfos = new SparseArray(4); /** * Helper class to store the ServiceInfo and the last message related to it. */ private static class TargetServiceInfo { @Nullable public final ServiceInfo serviceInfo; @Nullable public final String lastMessage; TargetServiceInfo(@Nullable ServiceInfo serviceInfo, @Nullable String lastMessage) { this.serviceInfo = serviceInfo; this.lastMessage = lastMessage; } } public AppServiceFinder(Context context, BiConsumer<AppServiceFinder, Integer> listener, Handler callbackHandler) { Loading Loading @@ -88,6 +117,7 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten mTargetPackages.delete(userId); mTargetServices.delete(userId); mLastMessages.delete(userId); mServiceInfos.delete(userId); } } Loading @@ -95,6 +125,7 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten * Find the target service from the target app on a given user. */ @Nullable @Deprecated public final ServiceInfo findService(int userId, IPackageManager ipm, AppBindingConstants constants) { synchronized (mLock) { Loading Loading @@ -155,6 +186,90 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten } } /** * Find the target service from the target app on a given user. */ @Nullable public final ServiceInfo findService(int userId, IPackageManager ipm, AppBindingConstants constants, String targetPackage) { synchronized (mLock) { HashMap<String, TargetServiceInfo> currServiceInfo = mServiceInfos.get(userId); if (DEBUG) { Slog.d(TAG, getAppDescription() + " package=" + targetPackage); } if (!isEnabled(constants, userId)) { final String message = "feature disabled"; currServiceInfo.put(targetPackage, new TargetServiceInfo(null, message)); Slog.i(TAG, getAppDescription() + " " + message); return null; } final StringBuilder errorMessage = new StringBuilder(); final ServiceInfo service = AppBindingUtils.findService( targetPackage, userId, getServiceAction(), getServicePermission(), getServiceClass(), ipm, errorMessage); if (service == null) { final String message = errorMessage.toString(); currServiceInfo.put(targetPackage, new TargetServiceInfo(null, message)); if (DEBUG) { Slog.w(TAG, getAppDescription() + " package " + targetPackage + " u" + userId + " " + message); } return null; } final String error = validateService(service); if (error != null) { currServiceInfo.put(targetPackage, new TargetServiceInfo(null, error)); Log.e(TAG, error); return null; } currServiceInfo.put(targetPackage, new TargetServiceInfo(service, "Valid service found")); return service; } } /** * Find the list of target service from the target apps on a given user. */ @Nullable public final List<ServiceInfo> findServices(int userId, IPackageManager ipm, AppBindingConstants constants) { final Set<String> targetPackages = getTargetPackages(userId); synchronized (mLock) { mServiceInfos.put(userId, new HashMap<String, TargetServiceInfo>()); if (DEBUG) { Slog.d(TAG, getAppDescription() + " packages=" + targetPackages); } if (!isEnabled(constants, userId) || targetPackages.isEmpty()) { final String message = (!isEnabled(constants, userId)) ? "feature disabled" : "Target packages not found"; mServiceInfos.get(userId).put(null, new TargetServiceInfo(null, message)); Slog.w(TAG, getAppDescription() + " u" + userId + " " + message); return new ArrayList<>(); } } List<ServiceInfo> services = new ArrayList<>(); for (String targetPackage: targetPackages) { ServiceInfo service = findService(userId, ipm, constants, targetPackage); if (service != null) { services.add(service); } } return services; } protected abstract Class<TServiceType> getServiceClass(); /** Loading @@ -166,8 +281,14 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten * @return the target package on a given user. */ @Nullable @Deprecated public abstract String getTargetPackage(int userId); /** * @return the target packages on a given user. */ public abstract Set<String> getTargetPackages(int userId); /** * @return the intent action that identifies the target service in the target app. */ Loading Loading @@ -199,6 +320,31 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten pw.println(); synchronized (mLock) { for (int i = 0; i < mServiceInfos.size(); i++) { final int userId = mServiceInfos.keyAt(i); pw.print(prefix); pw.print(" User: "); pw.print(userId); pw.println(); for (String targetPackage : mServiceInfos.get(userId).keySet()) { pw.print(prefix); pw.print(" Package: "); pw.print(targetPackage); pw.println(); pw.print(prefix); pw.print(" Service: "); pw.print(mServiceInfos.get(userId).get(targetPackage).serviceInfo); pw.println(); pw.print(prefix); pw.print(" Message: "); pw.print(mServiceInfos.get(userId).get(targetPackage).lastMessage); pw.println(); } pw.println(); } for (int i = 0; i < mTargetPackages.size(); i++) { final int userId = mTargetPackages.keyAt(i); pw.print(prefix); Loading Loading @@ -227,6 +373,16 @@ public abstract class AppServiceFinder<TServiceType, TServiceInterfaceType exten /** Dumpys support */ public void dumpSimple(PrintWriter pw) { synchronized (mLock) { for (int i = 0; i < mServiceInfos.size(); i++) { final int userId = mServiceInfos.keyAt(i); pw.println(String.format("finder,%s,%s", getAppDescription(), userId)); for (String targetPackage : mServiceInfos.get(userId).keySet()) { pw.println(String.format("finder,%s,%s,%s,%s,%s", getAppDescription(), userId, targetPackage, mServiceInfos.get(userId).get(targetPackage).serviceInfo, mServiceInfos.get(userId).get(targetPackage).lastMessage)); } } for (int i = 0; i < mTargetPackages.size(); i++) { final int userId = mTargetPackages.keyAt(i); pw.print("finder,"); Loading
services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java +19 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,9 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.util.CollectionUtils; import com.android.server.appbinding.AppBindingConstants; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; /** Loading Loading @@ -85,6 +88,7 @@ public class CarrierMessagingClientServiceFinder } @Override @Deprecated public String getTargetPackage(int userId) { final String ret = CollectionUtils.firstOrNull(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SMS, UserHandle.of(userId))); Loading @@ -96,6 +100,21 @@ public class CarrierMessagingClientServiceFinder return ret; } @Override public Set<String> getTargetPackages(int userId) { String targetPackage = CollectionUtils.firstOrNull(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SMS, UserHandle.of(userId))); if (DEBUG) { Slog.d(TAG, "getTargetPackages()=" + targetPackage); } if (targetPackage == null) { return Collections.emptySet(); } return new HashSet<>(Collections.singletonList(targetPackage)); } @Override public void startMonitoring() { mRoleManager.addOnRoleHoldersChangedListenerAsUser( Loading
services/core/java/com/android/server/appbinding/finders/SupervisionAppServiceFinder.java +13 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.appbinding.AppBindingConstants; import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; /** Finds the @{link SupervisionAppService} implementation within the supervision app. */ Loading Loading @@ -77,6 +79,7 @@ public class SupervisionAppServiceFinder @Nullable @Override @Deprecated public String getTargetPackage(int userId) { final String ret = CollectionUtils.firstOrNull( Loading @@ -85,6 +88,16 @@ public class SupervisionAppServiceFinder return ret; } @Override public Set<String> getTargetPackages(int userId) { final Set<String> ret = new HashSet<>(); ret.addAll(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SYSTEM_SUPERVISION, UserHandle.of(userId))); ret.addAll(mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SUPERVISION, UserHandle.of(userId))); return ret; } @NonNull @Override protected String getServiceAction() { Loading