Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6f496c7 authored by Lee Shombert's avatar Lee Shombert
Browse files

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
parent 065391ff
Loading
Loading
Loading
Loading
+69 −5
Original line number Diff line number Diff line
@@ -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);
    }