Merge "Adding an API that provides a map of shortcuts to be replaced." into udc-dev

This commit is contained in:
Nicolas Sleiman
2023-03-07 16:39:43 +00:00
committed by Android (Google) Code Review
8 changed files with 186 additions and 16 deletions

View File

@@ -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<>();
}
}
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -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 =

View File

@@ -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());

View File

@@ -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,

View File

@@ -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();
}
}

View File

@@ -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) {