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

Commit 9674823b authored by Jackal Guo's avatar Jackal Guo
Browse files

Apply visibility to get session info APIs

Callers need to either declare <queries> element with the specific
package name in the app's manifest, be the owner of the session, or
has appropriate permission to get the session infos.

Bug: 187176203
Bug: 187176993
Bug: 194694069
Bug: 194694094
Test: atest AppEnumerationTests
Test: manually using the PoC in the buganizer to ensure the symptom
      no longer exists.
Change-Id: I51e84e9560ebff3c5fcde1639542efd04a77557b
parent 75b6b1f2
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -1903,6 +1903,10 @@ public class LauncherApps {

    /**
     * Register a callback to watch for session lifecycle events in this user and managed profiles.
     * Callers need to either declare &lt;queries&gt; element with the specific package name in the
     * app's manifest, have the android.permission.QUERY_ALL_PACKAGES, or be the session owner to
     * watch for these events.
     *
     * @param callback The callback to register.
     * @param executor {@link Executor} to handle the callbacks, cannot be null.
     *
@@ -1947,7 +1951,9 @@ public class LauncherApps {

    /**
     * Return list of all known install sessions in this user and managed profiles, regardless
     * of the installer.
     * of the installer. Callers need to either declare &lt;queries&gt; element with the specific
     * package name in the app's manifest, have the android.permission.QUERY_ALL_PACKAGES, or be
     * the session owner to retrieve these details.
     *
     * @see PackageInstaller#getAllSessions()
     */
+26 −6
Original line number Diff line number Diff line
@@ -524,8 +524,9 @@ public class PackageInstaller {
    }

    /**
     * Return details for a specific session. No special permissions are
     * required to retrieve these details.
     * Return details for a specific session. Callers need to either declare &lt;queries&gt;
     * element with the specific package name in the app's manifest, have the
     * android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these details.
     *
     * @return details for the requested session, or {@code null} if the session
     *         does not exist.
@@ -539,7 +540,10 @@ public class PackageInstaller {
    }

    /**
     * Return list of all known install sessions, regardless of the installer.
     * Return list of all known install sessions, regardless of the installer. Callers need to
     * either declare &lt;queries&gt; element with the specific  package name in the app's manifest,
     * have the android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these
     * details.
     */
    public @NonNull List<SessionInfo> getAllSessions() {
        try {
@@ -561,7 +565,9 @@ public class PackageInstaller {
    }

    /**
     * Return list of all staged install sessions.
     * Return list of all staged install sessions. Callers need to either declare &lt;queries&gt;
     * element with the specific package name in the app's manifest, have the
     * android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these details.
     */
    public @NonNull List<SessionInfo> getStagedSessions() {
        try {
@@ -870,8 +876,8 @@ public class PackageInstaller {
    }

    /**
     * Register to watch for session lifecycle events. No special permissions
     * are required to watch for these events.
     * Register to watch for session lifecycle events. The callers need to be the session
     * owner or have the android.permission.QUERY_ALL_PACKAGES to watch for these events.
     */
    public void registerSessionCallback(@NonNull SessionCallback callback) {
        registerSessionCallback(callback, new Handler());
@@ -2397,6 +2403,9 @@ public class PackageInstaller {
        /** {@hide} */
        public int requireUserAction;

        /** {@hide} */
        public int installerUid;

        /** {@hide} */
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public SessionInfo() {
@@ -2447,6 +2456,7 @@ public class PackageInstaller {
            rollbackDataPolicy = source.readInt();
            createdMillis = source.readLong();
            requireUserAction = source.readInt();
            installerUid = source.readInt();
        }

        /**
@@ -2962,6 +2972,15 @@ public class PackageInstaller {
            return requireUserAction;
        }

        /**
         * Returns the Uid of the owner of the session.
         *
         * @hide
         */
        public int getInstallerUid() {
            return installerUid;
        }

        @Override
        public int describeContents() {
            return 0;
@@ -3008,6 +3027,7 @@ public class PackageInstaller {
            dest.writeInt(rollbackDataPolicy);
            dest.writeLong(createdMillis);
            dest.writeInt(requireUserAction);
            dest.writeInt(installerUid);
        }

        public static final Parcelable.Creator<SessionInfo>
+8 −0
Original line number Diff line number Diff line
@@ -781,6 +781,14 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
    @Nullable
    public abstract int[] getVisibilityAllowList(@NonNull String packageName, int userId);

    /**
     * Returns whether the given UID either declares &lt;queries&gt; element with the given package
     * name in its app's manifest, has {@link android.Manifest.permission.QUERY_ALL_PACKAGES}, or
     * package visibility filtering is enabled on it. If the UID is part of a shared user ID,
     * return {@code true} if any one application belongs to the shared user ID meets the criteria.
     */
    public abstract boolean canQueryPackage(int callingUid, @Nullable String packageName);

    /** Returns whether the given package was signed by the platform */
    public abstract boolean isPlatformSigned(String pkg);

+18 −0
Original line number Diff line number Diff line
@@ -1514,6 +1514,24 @@ public class AppsFilter implements Watchable, Snappable {
        }
    }

    boolean canQueryPackage(@NonNull AndroidPackage querying, String potentialTarget) {
        int appId = UserHandle.getAppId(querying.getUid());
        if (appId < Process.FIRST_APPLICATION_UID) {
            return true;
        }

        // Check if FILTER_APPLICATION_QUERY is enabled on the given package.
        if (!mFeatureConfig.packageIsEnabled(querying)) {
            return true;
        }

        if (requestsQueryAllPackages(querying)) {
            return true;
        }

        return !querying.getQueriesPackages().isEmpty()
                && querying.getQueriesPackages().contains(potentialTarget);
    }

    private static boolean requestsQueryAllPackages(@NonNull AndroidPackage pkg) {
        // we're not guaranteed to have permissions yet analyzed at package add, so we inspect the
+11 −1
Original line number Diff line number Diff line
@@ -278,6 +278,7 @@ public class LauncherAppsService extends SystemService {
            verifyCallingPackage(callingPackage);
            List<SessionInfo> sessionInfos = new ArrayList<>();
            int[] userIds = mUm.getEnabledProfileIds(getCallingUserId());
            final int callingUid = Binder.getCallingUid();
            final long token = Binder.clearCallingIdentity();
            try {
                for (int userId : userIds) {
@@ -287,9 +288,18 @@ public class LauncherAppsService extends SystemService {
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            sessionInfos.removeIf(info -> shouldFilterSession(callingUid, info));
            return new ParceledListSlice<>(sessionInfos);
        }

        private boolean shouldFilterSession(int uid, SessionInfo session) {
            if (session == null) {
                return false;
            }
            return uid != session.getInstallerUid()
                    && !mPackageManagerInternal.canQueryPackage(uid, session.getAppPackageName());
        }

        private PackageInstallerService getPackageInstallerService() {
            if (mPackageInstallerService == null) {
                mPackageInstallerService = ((PackageInstallerService) ((PackageManagerService)
@@ -377,7 +387,7 @@ public class LauncherAppsService extends SystemService {
        void verifyCallingPackage(String callingPackage) {
            int packageUid = -1;
            try {
                packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
                packageUid = mIPM.getPackageUid(callingPackage,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                | PackageManager.MATCH_UNINSTALLED_PACKAGES,
Loading