Cache default home

Bug: 162102512

Cache the default home app (package) in the slice manager.  The cache is
invalidated whenever the HOME role is changed.

Test: Tested with a debug build that computed the cached value and then
compared it to the original computation.  Verify that no discrepancies
are detected.
 * Manual test -
   1. Install the 3P Nova Launcher app.
   2. Choose Nova Launcher as the default home app
   3. Choose Pixel Launcher as the default home app
   4. Choose NOva Launcher as the default and then uninstall the app
 * FrameworksServicesTests:UserSystemPackageInstallerTest
 * UserLifecycleTests

Change-Id: I8e31acced3b41262641c522842e5f553c63af102
This commit is contained in:
Lee Shombert
2020-07-20 14:28:39 -07:00
parent 065391ffb9
commit b6f496c78a

View File

@@ -28,6 +28,8 @@ import static android.os.Process.SYSTEM_UID;
import android.Manifest.permission;
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.app.slice.ISliceManager;
import android.app.slice.SliceSpec;
import android.app.usage.UsageStatsManagerInternal;
@@ -77,6 +79,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
public class SliceManagerService extends ISliceManager.Stub {
@@ -121,6 +124,7 @@ public class SliceManagerService extends ISliceManager.Stub {
filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mRoleObserver = new RoleObserver();
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
}
@@ -478,10 +482,26 @@ public class SliceManagerService extends ISliceManager.Stub {
return cn.getPackageName();
}
/**
* A cached value of the default home app
*/
private String mCachedDefaultHome = null;
// Based on getDefaultHome in ShortcutService.
// TODO: Unify if possible
@VisibleForTesting
protected String getDefaultHome(int userId) {
// Set VERIFY to true to run the cache in "shadow" mode for cache
// testing. Do not commit set to true;
final boolean VERIFY = false;
if (mCachedDefaultHome != null) {
if (!VERIFY) {
return mCachedDefaultHome;
}
}
final long token = Binder.clearCallingIdentity();
try {
final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
@@ -490,10 +510,12 @@ public class SliceManagerService extends ISliceManager.Stub {
final ComponentName defaultLauncher = mPackageManagerInternal
.getHomeActivitiesAsUser(allHomeCandidates, userId);
ComponentName detected = null;
if (defaultLauncher != null) {
detected = defaultLauncher;
}
ComponentName detected = defaultLauncher;
// Cache the default launcher. It is not a problem if the
// launcher is null - eventually, the default launcher will be
// set to something non-null.
mCachedDefaultHome = ((detected != null) ? detected.getPackageName() : null);
if (detected == null) {
// If we reach here, that means it's the first check since the user was created,
@@ -517,12 +539,54 @@ public class SliceManagerService extends ISliceManager.Stub {
lastPriority = ri.priority;
}
}
return detected != null ? detected.getPackageName() : null;
final String ret = ((detected != null) ? detected.getPackageName() : null);
if (VERIFY) {
if (mCachedDefaultHome != null && !mCachedDefaultHome.equals(ret)) {
Slog.e(TAG, "getDefaultHome() cache failure, is " +
mCachedDefaultHome + " should be " + ret);
}
}
return ret;
} finally {
Binder.restoreCallingIdentity(token);
}
}
public void invalidateCachedDefaultHome() {
mCachedDefaultHome = null;
}
/**
* Listen for changes in the roles, and invalidate the cached default
* home as necessary.
*/
private RoleObserver mRoleObserver;
class RoleObserver implements OnRoleHoldersChangedListener {
private RoleManager mRm;
private final Executor mExecutor;
RoleObserver() {
mExecutor = mContext.getMainExecutor();
register();
}
public void register() {
mRm = mContext.getSystemService(RoleManager.class);
if (mRm != null) {
mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
invalidateCachedDefaultHome();
}
}
@Override
public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
if (RoleManager.ROLE_HOME.equals(roleName)) {
invalidateCachedDefaultHome();
}
}
}
private boolean isGrantedFullAccess(String pkg, int userId) {
return mPermissions.hasFullAccess(pkg, userId);
}