diff --git a/services/core/java/com/android/server/pm/DefaultAppProvider.java b/services/core/java/com/android/server/pm/DefaultAppProvider.java index c18d0e9ef35e0..fc61451b0289d 100644 --- a/services/core/java/com/android/server/pm/DefaultAppProvider.java +++ b/services/core/java/com/android/server/pm/DefaultAppProvider.java @@ -24,14 +24,10 @@ import android.os.Binder; import android.os.UserHandle; import android.util.Slog; -import com.android.internal.infra.AndroidFuture; import com.android.internal.util.CollectionUtils; import com.android.server.FgThread; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Supplier; @@ -70,27 +66,19 @@ public class DefaultAppProvider { * Set the package name of the default browser. * * @param packageName package name of the default browser, or {@code null} to unset - * @param async whether the operation should be asynchronous * @param userId the user ID - * @return whether the default browser was successfully set. */ - public boolean setDefaultBrowser(@Nullable String packageName, boolean async, - @UserIdInt int userId) { - if (userId == UserHandle.USER_ALL) { - return false; - } + public void setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) { final RoleManager roleManager = mRoleManagerSupplier.get(); if (roleManager == null) { - return false; + return; } final UserHandle user = UserHandle.of(userId); final Executor executor = FgThread.getExecutor(); - final AndroidFuture future = new AndroidFuture<>(); final Consumer callback = successful -> { - if (successful) { - future.complete(null); - } else { - future.completeExceptionally(new RuntimeException()); + if (!successful) { + Slog.e(PackageManagerService.TAG, "Failed to set default browser to " + + packageName); } }; final long identity = Binder.clearCallingIdentity(); @@ -102,19 +90,9 @@ public class DefaultAppProvider { roleManager.clearRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 0, user, executor, callback); } - if (!async) { - try { - future.get(5, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - Slog.e(PackageManagerService.TAG, "Exception while setting default browser: " - + packageName, e); - return false; - } - } } finally { Binder.restoreCallingIdentity(identity); } - return true; } /** diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2fc22bf79d919..dbc2fd89e58c6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3535,6 +3535,18 @@ public class PackageManagerService implements PackageSender, TestUtilityService // within these users. mPermissionManager.restoreDelayedRuntimePermissions(packageName, userId); + // Restore default browser setting if it is now installed. + String defaultBrowser; + synchronized (mLock) { + defaultBrowser = mSettings.getPendingDefaultBrowserLPr(userId); + } + if (Objects.equals(packageName, defaultBrowser)) { + mDefaultAppProvider.setDefaultBrowser(packageName, userId); + synchronized (mLock) { + mSettings.removePendingDefaultBrowserLPw(userId); + } + } + // Persistent preferred activity might have came into effect due to this // install. mPreferredActivityHelper.updateDefaultHomeNotLocked(snapshotComputer(), userId); @@ -6732,7 +6744,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public String removeLegacyDefaultBrowserPackageName(int userId) { synchronized (mLock) { - return mSettings.removeDefaultBrowserPackageNameLPw(userId); + return mSettings.removePendingDefaultBrowserLPw(userId); } } @@ -7569,8 +7581,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService callback); } - void setDefaultBrowser(@Nullable String packageName, boolean async, @UserIdInt int userId) { - mDefaultAppProvider.setDefaultBrowser(packageName, async, userId); + @Nullable + String getDefaultBrowser(@UserIdInt int userId) { + return mDefaultAppProvider.getDefaultBrowser(userId); + } + + void setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) { + mDefaultAppProvider.setDefaultBrowser(packageName, userId); } PackageUsage getPackageUsage() { diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java index 214a8b80b35d1..76e7070bd3feb 100644 --- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java +++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java @@ -557,9 +557,8 @@ final class PreferredActivityHelper { serializer.startDocument(null, true); serializer.startTag(null, TAG_DEFAULT_APPS); - synchronized (mPm.mLock) { - mPm.mSettings.writeDefaultAppsLPr(serializer, userId); - } + final String defaultBrowser = mPm.getDefaultBrowser(userId); + Settings.writeDefaultApps(serializer, defaultBrowser); serializer.endTag(null, TAG_DEFAULT_APPS); serializer.endDocument(); @@ -584,14 +583,19 @@ final class PreferredActivityHelper { parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name()); restoreFromXml(parser, userId, TAG_DEFAULT_APPS, (parser1, userId1) -> { - final String defaultBrowser; - synchronized (mPm.mLock) { - mPm.mSettings.readDefaultAppsLPw(parser1, userId1); - defaultBrowser = mPm.mSettings.removeDefaultBrowserPackageNameLPw( - userId1); - } + final String defaultBrowser = Settings.readDefaultApps(parser1); if (defaultBrowser != null) { - mPm.setDefaultBrowser(defaultBrowser, false, userId1); + final PackageStateInternal packageState = mPm.snapshotComputer() + .getPackageStateInternal(defaultBrowser); + if (packageState != null + && packageState.getUserStateOrDefault(userId1).isInstalled()) { + mPm.setDefaultBrowser(defaultBrowser, userId1); + } else { + synchronized (mPm.mLock) { + mPm.mSettings.setPendingDefaultBrowserLPw(defaultBrowser, + userId1); + } + } } }); } catch (Exception e) { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 532ae718c0304..677a5d11cc6b3 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -517,9 +517,11 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile private final WatchedArrayMap mRenamedPackages = new WatchedArrayMap(); - // For every user, it is used to find the package name of the default Browser App. + // For every user, it is used to find the package name of the default browser app pending to be + // applied, either on first boot after upgrade, or after backup & restore but before app is + // installed. @Watched - final WatchedSparseArray mDefaultBrowserApp = new WatchedSparseArray(); + final WatchedSparseArray mPendingDefaultBrowser = new WatchedSparseArray<>(); // TODO(b/161161364): This seems unused, and is probably not relevant in the new API, but should // verify. @@ -592,7 +594,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile mAppIds.registerObserver(mObserver); mRenamedPackages.registerObserver(mObserver); mNextAppLinkGeneration.registerObserver(mObserver); - mDefaultBrowserApp.registerObserver(mObserver); + mPendingDefaultBrowser.registerObserver(mObserver); mPendingPackages.registerObserver(mObserver); mPastSignatures.registerObserver(mObserver); mKeySetRefs.registerObserver(mObserver); @@ -787,7 +789,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile mRenamedPackages.snapshot(r.mRenamedPackages); mNextAppLinkGeneration.snapshot(r.mNextAppLinkGeneration); - mDefaultBrowserApp.snapshot(r.mDefaultBrowserApp); + mPendingDefaultBrowser.snapshot(r.mPendingDefaultBrowser); // mReadMessages mPendingPackages = r.mPendingPackagesSnapshot.snapshot(); mPendingPackagesSnapshot = new SnapshotCache.Sealed<>(); @@ -1504,8 +1506,16 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile return cpir; } - String removeDefaultBrowserPackageNameLPw(int userId) { - return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.removeReturnOld(userId); + String getPendingDefaultBrowserLPr(int userId) { + return mPendingDefaultBrowser.get(userId); + } + + void setPendingDefaultBrowserLPw(String defaultBrowser, int userId) { + mPendingDefaultBrowser.put(userId, defaultBrowser); + } + + String removePendingDefaultBrowserLPw(int userId) { + return mPendingDefaultBrowser.removeReturnOld(userId); } private File getUserSystemDirectory(int userId) { @@ -1688,6 +1698,19 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile void readDefaultAppsLPw(XmlPullParser parser, int userId) throws XmlPullParserException, IOException { + String defaultBrowser = readDefaultApps(parser); + if (defaultBrowser != null) { + mPendingDefaultBrowser.put(userId, defaultBrowser); + } + } + + /** + * @return the package name for the default browser app, or {@code null} if none. + */ + @Nullable + static String readDefaultApps(@NonNull XmlPullParser parser) + throws XmlPullParserException, IOException { + String defaultBrowser = null; int outerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT @@ -1697,8 +1720,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile } String tagName = parser.getName(); if (tagName.equals(TAG_DEFAULT_BROWSER)) { - String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME); - mDefaultBrowserApp.put(userId, packageName); + defaultBrowser = parser.getAttributeValue(null, ATTR_PACKAGE_NAME); } else if (tagName.equals(TAG_DEFAULT_DIALER)) { // Ignored. } else { @@ -1708,6 +1730,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile XmlUtils.skipCurrentTag(parser); } } + return defaultBrowser; } void readBlockUninstallPackagesLPw(TypedXmlPullParser parser, int userId) @@ -2087,8 +2110,13 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile void writeDefaultAppsLPr(XmlSerializer serializer, int userId) throws IllegalArgumentException, IllegalStateException, IOException { + String defaultBrowser = mPendingDefaultBrowser.get(userId); + writeDefaultApps(serializer, defaultBrowser); + } + + static void writeDefaultApps(@NonNull XmlSerializer serializer, @Nullable String defaultBrowser) + throws IllegalArgumentException, IllegalStateException, IOException { serializer.startTag(null, TAG_DEFAULT_APPS); - String defaultBrowser = mDefaultBrowserApp.get(userId); if (!TextUtils.isEmpty(defaultBrowser)) { serializer.startTag(null, TAG_DEFAULT_BROWSER); serializer.attribute(null, ATTR_PACKAGE_NAME, defaultBrowser);