Adding an API that provides a map of shortcuts to be replaced.
Adding an API in LauncherApps that returns a map of packages to LauncherActivityInfo. All launcher's shortcuts for the packages should point to the override's intent and profile id. This API when building the layout for the first time or after storage clear. This API is hidden as it should not be used outside of the Launcher. Bug: 265299249 Test: b/26951794 Change-Id: I3599e00f666edc61b9177eaec4f95e7e571acd44
This commit is contained in:
@@ -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.
|
||||
@@ -60,6 +63,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.
|
||||
*/
|
||||
@@ -85,5 +94,9 @@ public abstract class DevicePolicyCache {
|
||||
public boolean canAdminGrantSensorsPermissions() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public List<String> getLauncherShortcutOverrides() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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,12 +794,44 @@ 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.
|
||||
*
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1077,6 +1080,55 @@ public class LauncherAppsService extends SystemService {
|
||||
callingPackage, injectBinderCallingPid(), injectBinderCallingUid());
|
||||
}
|
||||
|
||||
@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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3518,16 +3518,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);
|
||||
@@ -7610,6 +7624,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.");
|
||||
@@ -7627,6 +7642,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void clearLauncherShortcutOverrides() {
|
||||
mPolicyCache.setLauncherShortcutOverrides(new ArrayList<>());
|
||||
}
|
||||
|
||||
private void updateTelephonyCrossProfileIntentFilters(int parentUserId, int profileUserId,
|
||||
boolean enableWorkTelephony) {
|
||||
try {
|
||||
@@ -22745,12 +22764,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) {
|
||||
|
||||
Reference in New Issue
Block a user