diff options
| author | 2023-03-07 16:39:43 +0000 | |
|---|---|---|
| committer | 2023-03-07 16:39:43 +0000 | |
| commit | 1e69f441e023edb7d2d727b14a8b5d6b7d8883ce (patch) | |
| tree | d76fba26db7dac3fce3a3b32999526fbd8d47c0d | |
| parent | c86ab980d7a5bbc872947eaef872932dc7037839 (diff) | |
| parent | 23cc38d526f35625d0de6ec22e3a82abdcc2e4e4 (diff) | |
Merge "Adding an API that provides a map of shortcuts to be replaced." into udc-dev
8 files changed, 186 insertions, 16 deletions
diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java index 3957732c56dd..b6e83c8bc8a1 100644 --- a/core/java/android/app/admin/DevicePolicyCache.java +++ b/core/java/android/app/admin/DevicePolicyCache.java @@ -19,6 +19,9 @@ import android.annotation.UserIdInt; import com.android.server.LocalServices; +import java.util.ArrayList; +import java.util.List; + /** * Stores a copy of the set of device policies maintained by {@link DevicePolicyManager} that * can be accessed from any place without risking dead locks. @@ -61,6 +64,12 @@ public abstract class DevicePolicyCache { public abstract boolean canAdminGrantSensorsPermissions(); /** + * Returns a list of package names for which all launcher shortcuts should be modified to be + * launched in the managed profile and badged accordingly. + */ + public abstract List<String> getLauncherShortcutOverrides(); + + /** * Empty implementation. */ private static class EmptyDevicePolicyCache extends DevicePolicyCache { @@ -85,5 +94,9 @@ public abstract class DevicePolicyCache { public boolean canAdminGrantSensorsPermissions() { return false; } + @Override + public List<String> getLauncherShortcutOverrides() { + return new ArrayList<>(); + } } } diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl index 08cfbf76a040..96a42e24bc1a 100644 --- a/core/java/android/content/pm/ILauncherApps.aidl +++ b/core/java/android/content/pm/ILauncherApps.aidl @@ -33,6 +33,7 @@ import android.content.pm.PackageInstaller; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; +import android.content.pm.LauncherActivityInfoInternal; import android.graphics.Rect; import android.os.Bundle; import android.os.UserHandle; @@ -114,4 +115,5 @@ interface ILauncherApps { String getShortcutIconUri(String callingPackage, String packageName, String shortcutId, int userId); + Map<String, LauncherActivityInfoInternal> getActivityOverrides(String callingPackage, int userId); } diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 16e720e3794c..a4d532712cfe 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -34,7 +34,6 @@ import android.util.DisplayMetrics; */ public class LauncherActivityInfo { private final PackageManager mPm; - private UserHandle mUser; private final LauncherActivityInfoInternal mInternal; /** @@ -43,9 +42,8 @@ public class LauncherActivityInfo { * @param context The context for fetching resources. */ - LauncherActivityInfo(Context context, UserHandle user, LauncherActivityInfoInternal internal) { + LauncherActivityInfo(Context context, LauncherActivityInfoInternal internal) { mPm = context.getPackageManager(); - mUser = user; mInternal = internal; } @@ -70,7 +68,7 @@ public class LauncherActivityInfo { * @return The UserHandle of the profile. */ public UserHandle getUser() { - return mUser; + return mInternal.getUser(); } /** @@ -180,6 +178,6 @@ public class LauncherActivityInfo { public Drawable getBadgedIcon(int density) { Drawable originalIcon = getIcon(density); - return mPm.getUserBadgedIcon(originalIcon, mUser); + return mPm.getUserBadgedIcon(originalIcon, mInternal.getUser()); } } diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.java b/core/java/android/content/pm/LauncherActivityInfoInternal.java index 46c415df7525..5aac97d784b3 100644 --- a/core/java/android/content/pm/LauncherActivityInfoInternal.java +++ b/core/java/android/content/pm/LauncherActivityInfoInternal.java @@ -21,6 +21,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; +import android.os.UserHandle; /** * @hide @@ -30,23 +31,27 @@ public class LauncherActivityInfoInternal implements Parcelable { @NonNull private ActivityInfo mActivityInfo; @NonNull private ComponentName mComponentName; @NonNull private IncrementalStatesInfo mIncrementalStatesInfo; + @NonNull private UserHandle mUser; /** * @param info ActivityInfo from which to create the LauncherActivityInfo. * @param incrementalStatesInfo The package's states. + * @param user The user the activity info belongs to. */ public LauncherActivityInfoInternal(@NonNull ActivityInfo info, - @NonNull IncrementalStatesInfo incrementalStatesInfo) { + @NonNull IncrementalStatesInfo incrementalStatesInfo, + @NonNull UserHandle user) { mActivityInfo = info; mComponentName = new ComponentName(info.packageName, info.name); mIncrementalStatesInfo = incrementalStatesInfo; + mUser = user; } public LauncherActivityInfoInternal(Parcel source) { - mActivityInfo = source.readParcelable(ActivityInfo.class.getClassLoader(), android.content.pm.ActivityInfo.class); + mActivityInfo = source.readTypedObject(ActivityInfo.CREATOR); mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name); - mIncrementalStatesInfo = source.readParcelable( - IncrementalStatesInfo.class.getClassLoader(), android.content.pm.IncrementalStatesInfo.class); + mIncrementalStatesInfo = source.readTypedObject(IncrementalStatesInfo.CREATOR); + mUser = source.readTypedObject(UserHandle.CREATOR); } public ComponentName getComponentName() { @@ -57,6 +62,10 @@ public class LauncherActivityInfoInternal implements Parcelable { return mActivityInfo; } + public UserHandle getUser() { + return mUser; + } + public IncrementalStatesInfo getIncrementalStatesInfo() { return mIncrementalStatesInfo; } @@ -68,8 +77,9 @@ public class LauncherActivityInfoInternal implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(mActivityInfo, 0); - dest.writeParcelable(mIncrementalStatesInfo, 0); + dest.writeTypedObject(mActivityInfo, flags); + dest.writeTypedObject(mIncrementalStatesInfo, flags); + dest.writeTypedObject(mUser, flags); } public static final @android.annotation.NonNull Creator<LauncherActivityInfoInternal> CREATOR = diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index f8c49744d834..8989006a7e83 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -64,6 +64,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.util.ArrayMap; import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; @@ -793,13 +794,45 @@ public class LauncherApps { if (ai == null) { return null; } - return new LauncherActivityInfo(mContext, user, ai); + return new LauncherActivityInfo(mContext, ai); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } } /** + * Returns overrides for the activities that should be launched for the shortcuts of certain + * package names. + * + * @return {@link Map} whose keys are package names and whose values are the + * {@link LauncherActivityInfo}s that should be used for those packages' shortcuts. If there are + * no activity overrides, an empty {@link Map} will be returned. + * + * @hide + */ + @NonNull + public Map<String, LauncherActivityInfo> getActivityOverrides() { + Map<String, LauncherActivityInfo> activityOverrides = new ArrayMap<>(); + try { + Map<String, LauncherActivityInfoInternal> activityOverridesInternal = + mService.getActivityOverrides(mContext.getPackageName(), mContext.getUserId()); + for (Map.Entry<String, LauncherActivityInfoInternal> packageToOverride : + activityOverridesInternal.entrySet()) { + activityOverrides.put( + packageToOverride.getKey(), + new LauncherActivityInfo( + mContext, + packageToOverride.getValue() + ) + ); + } + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + return activityOverrides; + } + + /** * Starts a Main activity in the specified profile. * * @param component The ComponentName of the activity to launch @@ -916,7 +949,7 @@ public class LauncherApps { } ArrayList<LauncherActivityInfo> lais = new ArrayList<>(); for (LauncherActivityInfoInternal internal : internals.getList()) { - LauncherActivityInfo lai = new LauncherActivityInfo(mContext, user, internal); + LauncherActivityInfo lai = new LauncherActivityInfo(mContext, internal); if (DEBUG) { Log.v(TAG, "Returning activity for profile " + user + " : " + lai.getComponentName()); diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 9e01c7af0f0b..84bee50b77b0 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -39,6 +39,7 @@ import android.app.ActivityOptions; import android.app.AppGlobals; import android.app.IApplicationThread; import android.app.PendingIntent; +import android.app.admin.DevicePolicyCache; import android.app.admin.DevicePolicyManager; import android.app.usage.UsageStatsManagerInternal; import android.content.ActivityNotFoundException; @@ -85,6 +86,7 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.util.ArrayMap; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -107,6 +109,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -623,7 +626,7 @@ public class LauncherAppsService extends SystemService { // package does not exist; should not happen return null; } - return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo); + return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo, user); } finally { Binder.restoreCallingIdentity(ident); } @@ -676,7 +679,7 @@ public class LauncherAppsService extends SystemService { continue; } results.add(new LauncherActivityInfoInternal(ri.activityInfo, - incrementalStatesInfo)); + incrementalStatesInfo, user)); } return results; } @@ -1078,6 +1081,55 @@ public class LauncherAppsService extends SystemService { } @Override + @NonNull + public Map<String, LauncherActivityInfoInternal> getActivityOverrides(String callingPackage, + int userId) { + ensureShortcutPermission(callingPackage); + int callingUid = Binder.getCallingUid(); + final long callerIdentity = Binder.clearCallingIdentity(); + try { + Map<String, LauncherActivityInfoInternal> shortcutOverridesInfo = new ArrayMap<>(); + UserHandle managedUserHandle = getManagedProfile(userId); + if (managedUserHandle == null) { + return shortcutOverridesInfo; + } + + List<String> packagesToOverride = + DevicePolicyCache.getInstance().getLauncherShortcutOverrides(); + for (String packageName : packagesToOverride) { + Intent intent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .setPackage(packageName); + + List<LauncherActivityInfoInternal> possibleShortcutOverrides = + queryIntentLauncherActivities( + intent, + callingUid, + managedUserHandle + ); + + if (!possibleShortcutOverrides.isEmpty()) { + shortcutOverridesInfo.put(packageName, possibleShortcutOverrides.get(0)); + } + } + return shortcutOverridesInfo; + } finally { + Binder.restoreCallingIdentity(callerIdentity); + } + } + + + @Nullable + private UserHandle getManagedProfile(int userId) { + for (UserInfo profile : mUm.getProfiles(userId)) { + if (profile.isManagedProfile()) { + return profile.getUserHandle(); + } + } + return null; + } + + @Override public boolean startShortcut(String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java index 4351bc1c81ce..80100a927e82 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java @@ -24,6 +24,8 @@ import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -52,6 +54,11 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { @GuardedBy("mLock") private final SparseIntArray mPermissionPolicy = new SparseIntArray(); + @GuardedBy("mLock") + private List<String> mLauncherShortcutOverrides = + new ArrayList<>(); + + /** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */ private final AtomicBoolean mCanGrantSensorsPermissions = new AtomicBoolean(false); @@ -122,6 +129,22 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { mCanGrantSensorsPermissions.set(canGrant); } + @Override + public List<String> getLauncherShortcutOverrides() { + synchronized (mLock) { + return new ArrayList<>(mLauncherShortcutOverrides); + } + } + + /** + * Sets a list of packages for which shortcuts should be replaced by their badged version. + */ + public void setLauncherShortcutOverrides(List<String> launcherShortcutOverrides) { + synchronized (mLock) { + mLauncherShortcutOverrides = new ArrayList<>(launcherShortcutOverrides); + } + } + /** Dump content */ public void dump(IndentingPrintWriter pw) { synchronized (mLock) { @@ -131,6 +154,8 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { pw.println("Password quality: " + mPasswordQuality); pw.println("Permission policy: " + mPermissionPolicy); pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions.get()); + pw.print("Shortcuts overrides: "); + pw.println(mLauncherShortcutOverrides); pw.decreaseIndent(); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 400ee1d3baf3..a4e563b21bec 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3522,16 +3522,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { userId == UserHandle.USER_SYSTEM ? UserHandle.USER_ALL : userId); updatePermissionPolicyCache(userId); updateAdminCanGrantSensorsPermissionCache(userId); - final List<PreferentialNetworkServiceConfig> preferentialNetworkServiceConfigs; + boolean isManagedSubscription; + synchronized (getLockObject()) { ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId); preferentialNetworkServiceConfigs = owner != null ? owner.mPreferentialNetworkServiceConfigs : List.of(PreferentialNetworkServiceConfig.DEFAULT); + + isManagedSubscription = owner != null && owner.mManagedSubscriptionsPolicy != null + && owner.mManagedSubscriptionsPolicy.getPolicyType() + == ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS; } updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfigs); + if (isManagedSubscription) { + String defaultDialerPackageName = getDefaultRoleHolderPackageName( + com.android.internal.R.string.config_defaultDialer); + String defaultSmsPackageName = getDefaultRoleHolderPackageName( + com.android.internal.R.string.config_defaultSms); + updateDialerAndSmsManagedShortcutsOverrideCache(defaultDialerPackageName, + defaultSmsPackageName); + } + startOwnerService(userId, "start-user"); if (isDevicePolicyEngineEnabled()) { mDevicePolicyEngine.handleStartUser(userId); @@ -7614,6 +7628,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (isWorkProfileTelephonyFlagEnabled()) { clearManagedSubscriptionsPolicy(); + clearLauncherShortcutOverrides(); updateTelephonyCrossProfileIntentFilters(parentId, UserHandle.USER_NULL, false); } Slogf.i(LOG_TAG, "Cleaning up device-wide policies done."); @@ -7631,6 +7646,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void clearLauncherShortcutOverrides() { + mPolicyCache.setLauncherShortcutOverrides(new ArrayList<>()); + } + private void updateTelephonyCrossProfileIntentFilters(int parentUserId, int profileUserId, boolean enableWorkTelephony) { try { @@ -22755,12 +22774,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else { Slogf.w(LOG_TAG, "Couldn't install sms app, sms app package is null"); } + + updateDialerAndSmsManagedShortcutsOverrideCache(defaultDialerPackageName, + defaultSmsPackageName); } catch (RemoteException re) { // shouldn't happen Slogf.wtf(LOG_TAG, "Failed to install dialer/sms app", re); } } + private void updateDialerAndSmsManagedShortcutsOverrideCache( + String defaultDialerPackageName, String defaultSmsPackageName) { + + List<String> shortcutOverrides = new ArrayList<>(); + + if (defaultDialerPackageName != null) { + shortcutOverrides.add(defaultDialerPackageName); + } + + if (defaultSmsPackageName != null) { + shortcutOverrides.add(defaultSmsPackageName); + } + mPolicyCache.setLauncherShortcutOverrides(shortcutOverrides); + } + private void registerListenerToAssignSubscriptionsToUser(int userId) { synchronized (mSubscriptionsChangedListenerLock) { if (mSubscriptionsChangedListener != null) { |