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

Commit 8286ffda authored by Ricky Wai's avatar Ricky Wai
Browse files

Remove hidden launchable app vouching code

Bug: 128279519
Test: Able to compile
Change-Id: Id121bf2a23a78b43f28963b7d76c5e5fa575a97f
parent e3cbf906
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -142,17 +142,6 @@ public class LauncherApps {
    public static final String EXTRA_PIN_ITEM_REQUEST =
            "android.content.pm.extra.PIN_ITEM_REQUEST";

    /**
     * Metadata key that specifies vouched certs, so any apps signed by a cert in vouched certs
     * will not show hidden icon in launcher even it does not have a launcher visible activity.
     *
     * If an app has this metadata in manifest, it won't be eligible to hide its icon even if its
     * cert is in vouched certs list.
     *
     * @hide
     */
    public static final String VOUCHED_CERTS_KEY = "vouched_certs";

    private final Context mContext;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final ILauncherApps mService;
+0 −159
Original line number Diff line number Diff line
@@ -45,8 +45,6 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.net.Uri;
@@ -62,31 +60,21 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.ByteStringUtils;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.wm.ActivityTaskManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Service that manages requests and callbacks for launchers that support
@@ -125,16 +113,6 @@ public class LauncherAppsService extends SystemService {
        private static final boolean DEBUG = false;
        private static final String TAG = "LauncherAppsService";

        // Stats
        @VisibleForTesting
        interface Stats {
            int INIT_VOUCHED_SIGNATURES = 0;
            int COUNT = INIT_VOUCHED_SIGNATURES + 1;
        }
        private final StatLogger mStatLogger = new StatLogger(new String[] {
                "initVouchedSignatures"
        });

        private final Context mContext;
        private final UserManager mUm;
        private final UserManagerInternal mUserManagerInternal;
@@ -145,16 +123,11 @@ public class LauncherAppsService extends SystemService {
        private final PackageCallbackList<IOnAppsChangedListener> mListeners
                = new PackageCallbackList<IOnAppsChangedListener>();
        private final DevicePolicyManager mDpm;
        private final ConcurrentHashMap<UserHandle, Set<String>> mVouchedSignaturesByUser;
        private final Set<String> mVouchProviders;

        private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
        private final VouchesChangedMonitor mVouchesChangedMonitor = new VouchesChangedMonitor();

        private final Handler mCallbackHandler;

        private final Object mVouchedSignaturesLocked = new Object();

        private PackageInstallerService mPackageInstallerService;

        public LauncherAppsImpl(Context context) {
@@ -173,9 +146,6 @@ public class LauncherAppsService extends SystemService {
            mShortcutServiceInternal.addListener(mPackageMonitor);
            mCallbackHandler = BackgroundThread.getHandler();
            mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
            mVouchedSignaturesByUser = new ConcurrentHashMap<>();
            mVouchProviders = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
            mVouchesChangedMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler);
        }

        @VisibleForTesting
@@ -468,32 +438,9 @@ public class LauncherAppsService extends SystemService {
            if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
                return false;
            }
            if (!mVouchedSignaturesByUser.containsKey(user)) {
                initVouchedSignatures(user);
            }
            if (isManagedProfileAdmin(user, appInfo.packageName)) {
                return false;
            }
            if (mVouchProviders.contains(appInfo.packageName)) {
                // If it's a vouching packages then we must show hidden app
                return true;
            }
            // If app's signature is in vouch list, do not show hidden app
            final Set<String> vouches = mVouchedSignaturesByUser.get(user);
            try {
                final PackageInfo pkgInfo = mContext.getPackageManager().getPackageInfo(
                        appInfo.packageName, PackageManager.GET_SIGNING_CERTIFICATES);
                final Signature[] signatures = getLatestSignatures(pkgInfo.signingInfo);
                // If any of the signatures appears in vouches, then we don't show hidden app
                for (Signature signature : signatures) {
                    final String certDigest = computePackageCertDigest(signature);
                    if (vouches.contains(certDigest)) {
                        return false;
                    }
                }
            } catch (PackageManager.NameNotFoundException e) {
                // Should not happen
            }
            return true;
        }

@@ -515,100 +462,6 @@ public class LauncherAppsService extends SystemService {
            return false;
        }

        @VisibleForTesting
        static String computePackageCertDigest(Signature signature) {
            MessageDigest messageDigest;
            try {
                messageDigest = MessageDigest.getInstance("SHA1");
            } catch (NoSuchAlgorithmException e) {
                // Should not happen
                return null;
            }
            messageDigest.update(signature.toByteArray());
            final byte[] digest = messageDigest.digest();
            return ByteStringUtils.toHexString(digest);
        }

        @VisibleForTesting
        static Signature[] getLatestSignatures(SigningInfo signingInfo) {
            if (signingInfo.hasMultipleSigners()) {
                return signingInfo.getApkContentsSigners();
            } else {
                final Signature[] signatures = signingInfo.getSigningCertificateHistory();
                return new Signature[]{signatures[0]};
            }
        }

        private void updateVouches(String packageName, UserHandle user) {
            final PackageManagerInternal pmInt =
                    LocalServices.getService(PackageManagerInternal.class);
            ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName,
                    PackageManager.GET_META_DATA, Binder.getCallingUid(), user.getIdentifier());
            if (appInfo == null) {
                Log.w(TAG, "appInfo " + packageName + " is null");
                return;
            }
            updateVouches(appInfo, user);
        }

        private void updateVouches(ApplicationInfo appInfo, UserHandle user) {
            if (appInfo == null || appInfo.metaData == null) {
                // No meta-data
                return;
            }
            int tokenResourceId = appInfo.metaData.getInt(LauncherApps.VOUCHED_CERTS_KEY);
            if (tokenResourceId == 0) {
                // No xml file
                return;
            }
            mVouchProviders.add(appInfo.packageName);
            Set<String> vouches = mVouchedSignaturesByUser.get(user);
            try {
                List<String> signatures = Arrays.asList(
                        mContext.getPackageManager().getResourcesForApplication(
                                appInfo.packageName).getStringArray(tokenResourceId));
                for (String signature : signatures) {
                    vouches.add(signature.toUpperCase());
                }
            } catch (PackageManager.NameNotFoundException e) {
                // Should not happen
            }
        }

        private void initVouchedSignatures(UserHandle user) {
            synchronized (mVouchedSignaturesLocked) {
                if (mVouchedSignaturesByUser.contains(user)) {
                    return;
                }
                final long startTime = mStatLogger.getTime();

                Set<String> vouches = Collections.newSetFromMap(
                        new ConcurrentHashMap<String, Boolean>());

                final int callingUid = injectBinderCallingUid();
                long ident = Binder.clearCallingIdentity();
                try {
                    final PackageManagerInternal pmInt =
                            LocalServices.getService(PackageManagerInternal.class);
                    List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(
                            PackageManager.GET_META_DATA, user.getIdentifier(), callingUid);
                    for (ApplicationInfo appInfo : installedPackages) {
                        updateVouches(appInfo, user);
                    }
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
                mVouchedSignaturesByUser.putIfAbsent(user, vouches);
                mStatLogger.logDurationStat(Stats.INIT_VOUCHED_SIGNATURES, startTime);
            }
        }

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
            mStatLogger.dump(pw, "  ");
        }

        @Override
        public ActivityInfo resolveActivity(
                String callingPackage, ComponentName component, UserHandle user)
@@ -1022,18 +875,6 @@ public class LauncherAppsService extends SystemService {
            mCallbackHandler.post(r);
        }

        private class VouchesChangedMonitor extends PackageMonitor {
            @Override
            public void onPackageAdded(String packageName, int uid) {
                updateVouches(packageName, new UserHandle(getChangingUserId()));
            }

            @Override
            public void onPackageModified(String packageName) {
                updateVouches(packageName, new UserHandle(getChangingUserId()));
            }
        }

        private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {

            // TODO Simplify with lambdas.
+0 −87
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.pm;

import static org.junit.Assert.assertEquals;

import android.content.pm.PackageParser;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
import android.platform.test.annotations.Presubmit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

@Presubmit
@RunWith(MockitoJUnitRunner.class)
public class LauncherAppsServiceTest {

    private static final Signature SIGNATURE_1 = new Signature(new byte[]{0x00, 0x01, 0x02, 0x03});
    private static final Signature SIGNATURE_2 = new Signature(new byte[]{0x04, 0x05, 0x06, 0x07});
    private static final Signature SIGNATURE_3 = new Signature(new byte[]{0x08, 0x09, 0x10, 0x11});

    @Test
    public void testComputePackageCertDigest() {
        String digest = LauncherAppsService.LauncherAppsImpl.computePackageCertDigest(SIGNATURE_1);
        assertEquals("A02A05B025B928C039CF1AE7E8EE04E7C190C0DB", digest);
    }

    @Test
    public void testGetLatestSignaturesWithSingleCert() {
        SigningInfo signingInfo = new SigningInfo(
                new PackageParser.SigningDetails(
                        new Signature[]{SIGNATURE_1},
                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
                        null,
                        null));
        Signature[] signatures = LauncherAppsService.LauncherAppsImpl.getLatestSignatures(
                signingInfo);
        assertEquals(1, signatures.length);
        assertEquals(SIGNATURE_1, signatures[0]);
    }

    @Test
    public void testGetLatestSignaturesWithMultiCert() {
        SigningInfo signingInfo = new SigningInfo(
                new PackageParser.SigningDetails(
                        new Signature[]{SIGNATURE_1, SIGNATURE_2},
                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
                        null,
                        null));
        Signature[] signatures = LauncherAppsService.LauncherAppsImpl.getLatestSignatures(
                signingInfo);
        assertEquals(2, signatures.length);
        assertEquals(SIGNATURE_1, signatures[0]);
        assertEquals(SIGNATURE_2, signatures[1]);
    }

    @Test
    public void testGetLatestSignaturesWithCertHistory() {
        SigningInfo signingInfo = new SigningInfo(
                new PackageParser.SigningDetails(
                        new Signature[]{SIGNATURE_1},
                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
                        null,
                        new Signature[]{SIGNATURE_2, SIGNATURE_3}));
        Signature[] signatures = LauncherAppsService.LauncherAppsImpl.getLatestSignatures(
                signingInfo);
        assertEquals(1, signatures.length);
        assertEquals(SIGNATURE_2, signatures[0]);
    }

}