Use role for default home.
This change makes package manager update the home role holder when
preferred activity for the home intent changes, in order to be
backward-compatible.
Bug: 124260975
Test: manual
Change-Id: I2f29e86f0db88d7e1edee74d0e911d33fef889c9
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index cfe35b0..270e387 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -163,6 +163,30 @@
}
/**
+ * Provider for default home
+ */
+ public interface DefaultHomeProvider {
+
+ /**
+ * Get the package name of the default home.
+ *
+ * @param userId the user id
+ *
+ * @return the package name of the default home, or {@code null} if none
+ */
+ @Nullable
+ String getDefaultHome(@UserIdInt int userId);
+
+ /**
+ * Set the package name of the default home.
+ *
+ * @param packageName package name of the default home, or {@code null} to remove
+ * @param userId the user id
+ */
+ void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId);
+ }
+
+ /**
* Sets the location provider packages provider.
* @param provider The packages provider.
*/
@@ -886,4 +910,11 @@
* @param provider the provider
*/
public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider);
+
+ /**
+ * Sets the default home provider.
+ *
+ * @param provider the provider
+ */
+ public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 874d1a7..aaf15d1c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -986,6 +986,9 @@
@GuardedBy("mPackages")
private PackageManagerInternal.DefaultBrowserProvider mDefaultBrowserProvider;
+ @GuardedBy("mPackages")
+ private PackageManagerInternal.DefaultHomeProvider mDefaultHomeProvider;
+
private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> {
private Context mContext;
private ComponentName mIntentFilterVerifierComponent;
@@ -1345,7 +1348,7 @@
final @Nullable String mRequiredVerifierPackage;
final @NonNull String mRequiredInstallerPackage;
final @NonNull String mRequiredUninstallerPackage;
- final String mRequiredPermissionControllerPackage;
+ final @NonNull String mRequiredPermissionControllerPackage;
final @Nullable String mSetupWizardPackage;
final @Nullable String mStorageManagerPackage;
final @Nullable String mSystemTextClassifierPackage;
@@ -1936,6 +1939,10 @@
// We may also need to apply pending (restored) runtime
// permission grants within these users.
mSettings.applyPendingPermissionGrantsLPw(packageName, userId);
+
+ // Persistent preferred activity might have came into effect due to this
+ // install.
+ updateDefaultHomeLPw(userId);
}
}
}
@@ -19104,6 +19111,7 @@
pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
scheduleWritePackageRestrictionsLocked(userId);
postPreferredActivityChangedBroadcast(userId);
+ updateDefaultHomeLPw(userId);
}
}
@@ -19254,6 +19262,13 @@
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
@GuardedBy("mPackages")
boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
+ return clearPackagePreferredActivitiesLPw(packageName, false, userId);
+ }
+
+ /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+ @GuardedBy("mPackages")
+ private boolean clearPackagePreferredActivitiesLPw(String packageName,
+ boolean skipUpdateDefaultHome, int userId) {
ArrayList<PreferredActivity> removed = null;
boolean changed = false;
for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
@@ -19282,6 +19297,9 @@
pir.removeFilter(pa);
}
changed = true;
+ if (!skipUpdateDefaultHome) {
+ updateDefaultHomeLPw(thisUserId);
+ }
}
}
if (changed) {
@@ -19341,8 +19359,9 @@
// writer
try {
synchronized (mPackages) {
- clearPackagePreferredActivitiesLPw(null, userId);
+ clearPackagePreferredActivitiesLPw(null, true, userId);
mSettings.applyDefaultPreferredAppsLPw(userId);
+ updateDefaultHomeLPw(userId);
// TODO: We have to reset the default SMS and Phone. This requires
// significant refactoring to keep all default apps in the package
// manager (cleaner but more work) or have the services provide
@@ -19411,6 +19430,7 @@
new PersistentPreferredActivity(filter, activity));
scheduleWritePackageRestrictionsLocked(userId);
postPreferredActivityChangedBroadcast(userId);
+ updateDefaultHomeLPw(userId);
}
}
@@ -19454,6 +19474,7 @@
if (changed) {
scheduleWritePackageRestrictionsLocked(userId);
postPreferredActivityChangedBroadcast(userId);
+ updateDefaultHomeLPw(userId);
}
}
}
@@ -19541,6 +19562,7 @@
(readParser, readUserId) -> {
synchronized (mPackages) {
mSettings.readPreferredActivitiesLPw(readParser, readUserId);
+ updateDefaultHomeLPw(readUserId);
}
});
} catch (Exception e) {
@@ -19955,19 +19977,59 @@
ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
int userId) {
Intent intent = getHomeIntent();
- List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
+ List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
PackageManager.GET_META_DATA, userId);
- ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
- true, false, false, userId);
-
allHomeCandidates.clear();
- if (list != null) {
- allHomeCandidates.addAll(list);
+ if (resolveInfos == null) {
+ return null;
}
- return (preferred == null || preferred.activityInfo == null)
- ? null
- : new ComponentName(preferred.activityInfo.packageName,
- preferred.activityInfo.name);
+ allHomeCandidates.addAll(resolveInfos);
+
+ PackageManagerInternal.DefaultHomeProvider provider;
+ synchronized (mPackages) {
+ provider = mDefaultHomeProvider;
+ }
+ if (provider == null) {
+ Slog.e(TAG, "mDefaultHomeProvider is null");
+ return null;
+ }
+ String packageName = provider.getDefaultHome(userId);
+ if (packageName == null) {
+ return null;
+ }
+ int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+
+ if (resolveInfo.activityInfo != null && TextUtils.equals(
+ resolveInfo.activityInfo.packageName, packageName)) {
+ return new ComponentName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
+ }
+ }
+ return null;
+ }
+
+ private void updateDefaultHomeLPw(int userId) {
+ Intent intent = getHomeIntent();
+ List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
+ PackageManager.GET_META_DATA, userId);
+ ResolveInfo preferredResolveInfo = findPreferredActivity(intent, null, 0, resolveInfos,
+ 0, true, false, false, userId);
+ String packageName = preferredResolveInfo != null
+ && preferredResolveInfo.activityInfo != null
+ ? preferredResolveInfo.activityInfo.packageName : null;
+ String currentPackageName = mDefaultHomeProvider.getDefaultHome(userId);
+ if (TextUtils.equals(currentPackageName, packageName)) {
+ return;
+ }
+ String[] callingPackages = getPackagesForUid(Binder.getCallingUid());
+ if (callingPackages != null && ArrayUtils.contains(callingPackages,
+ mRequiredPermissionControllerPackage)) {
+ // PermissionController manages default home directly.
+ return;
+ }
+ mDefaultHomeProvider.setDefaultHomeAsync(packageName, userId);
}
@Override
@@ -23901,6 +23963,13 @@
mDefaultBrowserProvider = provider;
}
}
+
+ @Override
+ public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) {
+ synchronized (mPackages) {
+ mDefaultHomeProvider = provider;
+ }
+ }
}
@GuardedBy("mPackages")
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 3534cf3..888dd99 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -17,10 +17,13 @@
package com.android.server.policy.role;
import android.annotation.NonNull;
+import android.annotation.UserIdInt;
import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
import android.os.Debug;
import android.provider.Settings;
import android.telecom.TelecomManager;
@@ -33,6 +36,7 @@
import com.android.server.LocalServices;
import com.android.server.role.RoleManagerService;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -54,19 +58,44 @@
@NonNull
private final Context mContext;
- public LegacyRoleResolutionPolicy(Context context) {
+ public LegacyRoleResolutionPolicy(@NonNull Context context) {
mContext = context;
}
+ @NonNull
@Override
- public List<String> getRoleHolders(String roleName, int userId) {
+ public List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
switch (roleName) {
+ case RoleManager.ROLE_ASSISTANT: {
+ String legacyAssistant = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId);
+ if (legacyAssistant == null || legacyAssistant.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ return Collections.singletonList(
+ ComponentName.unflattenFromString(legacyAssistant).getPackageName());
+ }
+ }
+ case RoleManager.ROLE_BROWSER: {
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName(
+ userId);
+ return CollectionUtils.singletonOrEmpty(packageName);
+ }
+ case RoleManager.ROLE_DIALER: {
+ String setting = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
+ return CollectionUtils.singletonOrEmpty(!TextUtils.isEmpty(setting)
+ ? setting
+ : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage());
+ }
case RoleManager.ROLE_SMS: {
// Moved over from SmsApplication#getApplication
String result = Settings.Secure.getStringForUser(
mContext.getContentResolver(),
Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
-
// TODO: STOPSHIP: Remove the following code once we read the value of
// config_defaultSms in RoleControllerService.
if (result == null) {
@@ -92,34 +121,13 @@
SmsApplication.SmsApplicationData app = applicationData;
result = app == null ? null : app.mPackageName;
}
-
return CollectionUtils.singletonOrEmpty(result);
}
- case RoleManager.ROLE_ASSISTANT: {
- String legacyAssistant = Settings.Secure.getStringForUser(
- mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId);
-
- if (legacyAssistant == null || legacyAssistant.isEmpty()) {
- return Collections.emptyList();
- } else {
- return Collections.singletonList(
- ComponentName.unflattenFromString(legacyAssistant).getPackageName());
- }
- }
- case RoleManager.ROLE_DIALER: {
- String setting = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
-
- return CollectionUtils.singletonOrEmpty(!TextUtils.isEmpty(setting)
- ? setting
- : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage());
- }
- case RoleManager.ROLE_BROWSER: {
- PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
- String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName(
- userId);
+ case RoleManager.ROLE_HOME: {
+ PackageManager packageManager = mContext.getPackageManager();
+ List<ResolveInfo> resolveInfos = new ArrayList<>();
+ ComponentName componentName = packageManager.getHomeActivities(resolveInfos);
+ String packageName = componentName != null ? componentName.getPackageName() : null;
return CollectionUtils.singletonOrEmpty(packageName);
}
default: {
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 21bf9de..d853121 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -111,7 +111,8 @@
/** @see #getRoleHolders(String, int) */
public interface RoleHoldersResolver {
/** @return a list of packages that hold a given role for a given user */
- List<String> getRoleHolders(String roleName, int userId);
+ @NonNull
+ List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId);
}
/**
@@ -154,6 +155,7 @@
PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
packageManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider());
+ packageManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider());
registerUserRemovedReceiver();
}
@@ -741,4 +743,33 @@
}
}
}
+
+ private class DefaultHomeProvider implements PackageManagerInternal.DefaultHomeProvider {
+
+ @Nullable
+ @Override
+ public String getDefaultHome(@UserIdInt int userId) {
+ return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders(
+ RoleManager.ROLE_HOME));
+ }
+
+ @Override
+ public void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId) {
+ IRoleManagerCallback callback = new IRoleManagerCallback.Stub() {
+ @Override
+ public void onSuccess() {}
+ @Override
+ public void onFailure() {
+ Slog.e(LOG_TAG, "Failed to set default home: " + packageName);
+ }
+ };
+ if (packageName != null) {
+ getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
+ packageName, 0, callback);
+ } else {
+ getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
+ callback);
+ }
+ }
+ }
}