Loading core/java/android/app/communal/CommunalManager.java +1 −25 Original line number Diff line number Diff line Loading @@ -23,9 +23,6 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.Overridable; import android.content.Context; import android.content.pm.PackageManager; import android.os.RemoteException; Loading @@ -46,31 +43,10 @@ public final class CommunalManager { private final ICommunalManager mService; private final ArrayMap<CommunalModeListener, ICommunalModeListener> mCommunalModeListeners; /** * This change id is used to annotate packages which can run in communal mode by default, * without requiring user opt-in. * * @hide */ @ChangeId @Overridable @Disabled public static final long ALLOW_COMMUNAL_MODE_BY_DEFAULT = 203673428L; /** * This change id is used to annotate packages which are allowed to run in communal mode. * * @hide */ @ChangeId @Overridable @Disabled public static final long ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT = 200324021L; /** @hide */ public CommunalManager(ICommunalManager service) { mService = service; mCommunalModeListeners = new ArrayMap<CommunalModeListener, ICommunalModeListener>(); mCommunalModeListeners = new ArrayMap<>(); } /** Loading core/java/android/provider/Settings.java +0 −7 Original line number Diff line number Diff line Loading @@ -10489,13 +10489,6 @@ public final class Settings { */ public static final String COMMUNAL_MODE_ENABLED = "communal_mode_enabled"; /** * An array of all the packages which have been enabled for hub mode by the user. * * @hide */ public static final String COMMUNAL_MODE_PACKAGES = "communal_mode_packages"; /** * An array of SSIDs of Wi-Fi networks that, when connected, are considered safe to enable * the communal mode. Loading services/core/java/com/android/server/communal/CommunalManagerService.java +0 −239 Original line number Diff line number Diff line Loading @@ -16,117 +16,34 @@ package com.android.server.communal; import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_BY_DEFAULT; import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static com.android.server.wm.ActivityInterceptorCallback.COMMUNAL_MODE_ORDERED_ID; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.KeyguardManager; import android.app.PendingIntent; import android.app.communal.ICommunalManager; import android.app.communal.ICommunalModeListener; import android.app.compat.CompatChanges; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.IIntentSender; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.DreamManagerInternal; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.LaunchAfterAuthenticationActivity; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.wm.ActivityInterceptorCallback; import com.android.server.wm.ActivityTaskManagerInternal; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** * System service for handling Communal Mode state. */ public final class CommunalManagerService extends SystemService { private static final String TAG = CommunalManagerService.class.getSimpleName(); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String DELIMITER = ","; private final Context mContext; private final ActivityTaskManagerInternal mAtmInternal; private final KeyguardManager mKeyguardManager; private final AtomicBoolean mCommunalViewIsShowing = new AtomicBoolean(false); private final BinderService mBinderService; private final PackageReceiver mPackageReceiver; private final PackageManager mPackageManager; private final DreamManagerInternal mDreamManagerInternal; private final RemoteCallbackList<ICommunalModeListener> mListeners = new RemoteCallbackList<>(); private final ActivityInterceptorCallback mActivityInterceptorCallback = new ActivityInterceptorCallback() { @Nullable @Override public ActivityInterceptResult intercept(ActivityInterceptorInfo info) { if (!shouldIntercept(info.aInfo)) { if (DEBUG) { Slog.d(TAG, "Activity allowed, not intercepting: " + info.aInfo.getComponentName()); } return null; } final IIntentSender target = mAtmInternal.getIntentSender( INTENT_SENDER_ACTIVITY, info.callingPackage, info.callingFeatureId, info.callingUid, info.userId, /* token= */null, /* resultWho= */ null, /* requestCode= */ 0, new Intent[]{info.intent}, new String[]{info.resolvedType}, PendingIntent.FLAG_IMMUTABLE, /* bOptions= */ null); return new ActivityInterceptResult( LaunchAfterAuthenticationActivity.createLaunchAfterAuthenticationIntent( new IntentSender(target)), info.checkedOptions); } }; public CommunalManagerService(Context context) { super(context); mContext = context; mPackageManager = mContext.getPackageManager(); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); mKeyguardManager = mContext.getSystemService(KeyguardManager.class); mBinderService = new BinderService(); mPackageReceiver = new PackageReceiver(mContext); } @VisibleForTesting Loading @@ -139,116 +56,6 @@ public final class CommunalManagerService extends SystemService { publishBinderService(Context.COMMUNAL_SERVICE, mBinderService); } @Override public void onBootPhase(int phase) { if (phase != SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) return; mAtmInternal.registerActivityStartInterceptor( COMMUNAL_MODE_ORDERED_ID, mActivityInterceptorCallback); mPackageReceiver.register(); removeUninstalledPackagesFromSettings(); } @Override public void finalize() { mPackageReceiver.unregister(); } private Set<String> getUserEnabledApps() { final String encodedApps = Settings.Secure.getStringForUser( mContext.getContentResolver(), Settings.Secure.COMMUNAL_MODE_PACKAGES, UserHandle.USER_SYSTEM); return TextUtils.isEmpty(encodedApps) ? Collections.emptySet() : new HashSet<>(Arrays.asList(encodedApps.split(DELIMITER))); } private void removeUninstalledPackagesFromSettings() { for (String packageName : getUserEnabledApps()) { if (!isPackageInstalled(packageName, mPackageManager)) { removePackageFromSettings(packageName); } } } private void removePackageFromSettings(String packageName) { Set<String> enabledPackages = getUserEnabledApps(); if (enabledPackages.remove(packageName)) { Settings.Secure.putStringForUser( mContext.getContentResolver(), Settings.Secure.COMMUNAL_MODE_PACKAGES, String.join(DELIMITER, enabledPackages), UserHandle.USER_SYSTEM); } } @VisibleForTesting static boolean isPackageInstalled(String packageName, PackageManager packageManager) { if (packageManager == null) return false; try { return packageManager.getPackageInfo(packageName, 0) != null; } catch (PackageManager.NameNotFoundException e) { return false; } } private boolean isAppAllowed(ApplicationInfo appInfo) { if (isActiveDream(appInfo) || isChangeEnabled(ALLOW_COMMUNAL_MODE_BY_DEFAULT, appInfo)) { return true; } if (!isChangeEnabled(ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT, appInfo)) { if (DEBUG) Slog.d(TAG, "App is not allowlisted: " + appInfo.packageName); return false; } if (!getUserEnabledApps().contains(appInfo.packageName)) { if (DEBUG) Slog.d(TAG, "App does not have user consent: " + appInfo.packageName); return false; } return true; } private boolean isActiveDream(ApplicationInfo appInfo) { final ComponentName activeDream = mDreamManagerInternal.getActiveDreamComponent( /* doze= */ false); final ComponentName activeDoze = mDreamManagerInternal.getActiveDreamComponent( /* doze= */ true); return isFromPackage(activeDream, appInfo) || isFromPackage(activeDoze, appInfo); } private static boolean isFromPackage(ComponentName componentName, ApplicationInfo appInfo) { if (componentName == null) return false; return TextUtils.equals(appInfo.packageName, componentName.getPackageName()); } private static boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { return CompatChanges.isChangeEnabled(changeId, appInfo.packageName, UserHandle.SYSTEM); } private boolean shouldIntercept(ActivityInfo activityInfo) { if (!mCommunalViewIsShowing.get() || !mKeyguardManager.isKeyguardLocked()) return false; ApplicationInfo appInfo = activityInfo.applicationInfo; // Dreams are allowed to show, and don't require the showWhenLocked attribute. if (isActiveDream(appInfo)) return false; // If the activity doesn't have showWhenLocked enabled, disallow the activity. final boolean showWhenLocked = (activityInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0; if (!showWhenLocked) { if (DEBUG) { Slog.d(TAG, "Activity does not contain showWhenLocked attribute: " + activityInfo.getComponentName()); } return true; } return !isAppAllowed(appInfo); } private void dispatchCommunalMode(boolean isShowing) { synchronized (mListeners) { int i = mListeners.beginBroadcast(); Loading Loading @@ -319,50 +126,4 @@ public final class CommunalManagerService extends SystemService { } } } /** * A {@link BroadcastReceiver} that listens on package removed events and updates any stored * package state in Settings. */ private final class PackageReceiver extends BroadcastReceiver { private final Context mContext; private final IntentFilter mIntentFilter; private PackageReceiver(Context context) { mContext = context; mIntentFilter = new IntentFilter(); mIntentFilter.addAction(ACTION_PACKAGE_REMOVED); mIntentFilter.addDataScheme("package"); } private void register() { mContext.registerReceiverAsUser( this, UserHandle.SYSTEM, mIntentFilter, /* broadcastPermission= */null, /* scheduler= */ null, Context.RECEIVER_EXPORTED_UNAUDITED); } private void unregister() { mContext.unregisterReceiver(this); } @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { final Uri data = intent.getData(); if (data == null) { Slog.w(TAG, "Failed to get package name in package receiver"); return; } final String packageName = data.getSchemeSpecificPart(); final String action = intent.getAction(); if (ACTION_PACKAGE_REMOVED.equals(action)) { removePackageFromSettings(packageName); } else { Slog.w(TAG, "Unsupported action in package receiver: " + action); } } } } services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java +0 −267 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/app/communal/CommunalManager.java +1 −25 Original line number Diff line number Diff line Loading @@ -23,9 +23,6 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.Overridable; import android.content.Context; import android.content.pm.PackageManager; import android.os.RemoteException; Loading @@ -46,31 +43,10 @@ public final class CommunalManager { private final ICommunalManager mService; private final ArrayMap<CommunalModeListener, ICommunalModeListener> mCommunalModeListeners; /** * This change id is used to annotate packages which can run in communal mode by default, * without requiring user opt-in. * * @hide */ @ChangeId @Overridable @Disabled public static final long ALLOW_COMMUNAL_MODE_BY_DEFAULT = 203673428L; /** * This change id is used to annotate packages which are allowed to run in communal mode. * * @hide */ @ChangeId @Overridable @Disabled public static final long ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT = 200324021L; /** @hide */ public CommunalManager(ICommunalManager service) { mService = service; mCommunalModeListeners = new ArrayMap<CommunalModeListener, ICommunalModeListener>(); mCommunalModeListeners = new ArrayMap<>(); } /** Loading
core/java/android/provider/Settings.java +0 −7 Original line number Diff line number Diff line Loading @@ -10489,13 +10489,6 @@ public final class Settings { */ public static final String COMMUNAL_MODE_ENABLED = "communal_mode_enabled"; /** * An array of all the packages which have been enabled for hub mode by the user. * * @hide */ public static final String COMMUNAL_MODE_PACKAGES = "communal_mode_packages"; /** * An array of SSIDs of Wi-Fi networks that, when connected, are considered safe to enable * the communal mode. Loading
services/core/java/com/android/server/communal/CommunalManagerService.java +0 −239 Original line number Diff line number Diff line Loading @@ -16,117 +16,34 @@ package com.android.server.communal; import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_BY_DEFAULT; import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static com.android.server.wm.ActivityInterceptorCallback.COMMUNAL_MODE_ORDERED_ID; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.KeyguardManager; import android.app.PendingIntent; import android.app.communal.ICommunalManager; import android.app.communal.ICommunalModeListener; import android.app.compat.CompatChanges; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.IIntentSender; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.DreamManagerInternal; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.LaunchAfterAuthenticationActivity; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.wm.ActivityInterceptorCallback; import com.android.server.wm.ActivityTaskManagerInternal; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** * System service for handling Communal Mode state. */ public final class CommunalManagerService extends SystemService { private static final String TAG = CommunalManagerService.class.getSimpleName(); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String DELIMITER = ","; private final Context mContext; private final ActivityTaskManagerInternal mAtmInternal; private final KeyguardManager mKeyguardManager; private final AtomicBoolean mCommunalViewIsShowing = new AtomicBoolean(false); private final BinderService mBinderService; private final PackageReceiver mPackageReceiver; private final PackageManager mPackageManager; private final DreamManagerInternal mDreamManagerInternal; private final RemoteCallbackList<ICommunalModeListener> mListeners = new RemoteCallbackList<>(); private final ActivityInterceptorCallback mActivityInterceptorCallback = new ActivityInterceptorCallback() { @Nullable @Override public ActivityInterceptResult intercept(ActivityInterceptorInfo info) { if (!shouldIntercept(info.aInfo)) { if (DEBUG) { Slog.d(TAG, "Activity allowed, not intercepting: " + info.aInfo.getComponentName()); } return null; } final IIntentSender target = mAtmInternal.getIntentSender( INTENT_SENDER_ACTIVITY, info.callingPackage, info.callingFeatureId, info.callingUid, info.userId, /* token= */null, /* resultWho= */ null, /* requestCode= */ 0, new Intent[]{info.intent}, new String[]{info.resolvedType}, PendingIntent.FLAG_IMMUTABLE, /* bOptions= */ null); return new ActivityInterceptResult( LaunchAfterAuthenticationActivity.createLaunchAfterAuthenticationIntent( new IntentSender(target)), info.checkedOptions); } }; public CommunalManagerService(Context context) { super(context); mContext = context; mPackageManager = mContext.getPackageManager(); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); mKeyguardManager = mContext.getSystemService(KeyguardManager.class); mBinderService = new BinderService(); mPackageReceiver = new PackageReceiver(mContext); } @VisibleForTesting Loading @@ -139,116 +56,6 @@ public final class CommunalManagerService extends SystemService { publishBinderService(Context.COMMUNAL_SERVICE, mBinderService); } @Override public void onBootPhase(int phase) { if (phase != SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) return; mAtmInternal.registerActivityStartInterceptor( COMMUNAL_MODE_ORDERED_ID, mActivityInterceptorCallback); mPackageReceiver.register(); removeUninstalledPackagesFromSettings(); } @Override public void finalize() { mPackageReceiver.unregister(); } private Set<String> getUserEnabledApps() { final String encodedApps = Settings.Secure.getStringForUser( mContext.getContentResolver(), Settings.Secure.COMMUNAL_MODE_PACKAGES, UserHandle.USER_SYSTEM); return TextUtils.isEmpty(encodedApps) ? Collections.emptySet() : new HashSet<>(Arrays.asList(encodedApps.split(DELIMITER))); } private void removeUninstalledPackagesFromSettings() { for (String packageName : getUserEnabledApps()) { if (!isPackageInstalled(packageName, mPackageManager)) { removePackageFromSettings(packageName); } } } private void removePackageFromSettings(String packageName) { Set<String> enabledPackages = getUserEnabledApps(); if (enabledPackages.remove(packageName)) { Settings.Secure.putStringForUser( mContext.getContentResolver(), Settings.Secure.COMMUNAL_MODE_PACKAGES, String.join(DELIMITER, enabledPackages), UserHandle.USER_SYSTEM); } } @VisibleForTesting static boolean isPackageInstalled(String packageName, PackageManager packageManager) { if (packageManager == null) return false; try { return packageManager.getPackageInfo(packageName, 0) != null; } catch (PackageManager.NameNotFoundException e) { return false; } } private boolean isAppAllowed(ApplicationInfo appInfo) { if (isActiveDream(appInfo) || isChangeEnabled(ALLOW_COMMUNAL_MODE_BY_DEFAULT, appInfo)) { return true; } if (!isChangeEnabled(ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT, appInfo)) { if (DEBUG) Slog.d(TAG, "App is not allowlisted: " + appInfo.packageName); return false; } if (!getUserEnabledApps().contains(appInfo.packageName)) { if (DEBUG) Slog.d(TAG, "App does not have user consent: " + appInfo.packageName); return false; } return true; } private boolean isActiveDream(ApplicationInfo appInfo) { final ComponentName activeDream = mDreamManagerInternal.getActiveDreamComponent( /* doze= */ false); final ComponentName activeDoze = mDreamManagerInternal.getActiveDreamComponent( /* doze= */ true); return isFromPackage(activeDream, appInfo) || isFromPackage(activeDoze, appInfo); } private static boolean isFromPackage(ComponentName componentName, ApplicationInfo appInfo) { if (componentName == null) return false; return TextUtils.equals(appInfo.packageName, componentName.getPackageName()); } private static boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { return CompatChanges.isChangeEnabled(changeId, appInfo.packageName, UserHandle.SYSTEM); } private boolean shouldIntercept(ActivityInfo activityInfo) { if (!mCommunalViewIsShowing.get() || !mKeyguardManager.isKeyguardLocked()) return false; ApplicationInfo appInfo = activityInfo.applicationInfo; // Dreams are allowed to show, and don't require the showWhenLocked attribute. if (isActiveDream(appInfo)) return false; // If the activity doesn't have showWhenLocked enabled, disallow the activity. final boolean showWhenLocked = (activityInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0; if (!showWhenLocked) { if (DEBUG) { Slog.d(TAG, "Activity does not contain showWhenLocked attribute: " + activityInfo.getComponentName()); } return true; } return !isAppAllowed(appInfo); } private void dispatchCommunalMode(boolean isShowing) { synchronized (mListeners) { int i = mListeners.beginBroadcast(); Loading Loading @@ -319,50 +126,4 @@ public final class CommunalManagerService extends SystemService { } } } /** * A {@link BroadcastReceiver} that listens on package removed events and updates any stored * package state in Settings. */ private final class PackageReceiver extends BroadcastReceiver { private final Context mContext; private final IntentFilter mIntentFilter; private PackageReceiver(Context context) { mContext = context; mIntentFilter = new IntentFilter(); mIntentFilter.addAction(ACTION_PACKAGE_REMOVED); mIntentFilter.addDataScheme("package"); } private void register() { mContext.registerReceiverAsUser( this, UserHandle.SYSTEM, mIntentFilter, /* broadcastPermission= */null, /* scheduler= */ null, Context.RECEIVER_EXPORTED_UNAUDITED); } private void unregister() { mContext.unregisterReceiver(this); } @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { final Uri data = intent.getData(); if (data == null) { Slog.w(TAG, "Failed to get package name in package receiver"); return; } final String packageName = data.getSchemeSpecificPart(); final String action = intent.getAction(); if (ACTION_PACKAGE_REMOVED.equals(action)) { removePackageFromSettings(packageName); } else { Slog.w(TAG, "Unsupported action in package receiver: " + action); } } } }
services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java +0 −267 File changed.Preview size limit exceeded, changes collapsed. Show changes