Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.pm;
     18 
     19 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     20 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
     21 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
     22 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
     23 
     24 import android.annotation.NonNull;
     25 import android.content.Context;
     26 import android.content.pm.PackageParser;
     27 import android.content.pm.UserInfo;
     28 import android.os.UserHandle;
     29 import android.test.AndroidTestCase;
     30 import android.util.ArrayMap;
     31 import android.util.ArraySet;
     32 import android.util.Log;
     33 import android.util.LongSparseArray;
     34 
     35 import com.android.internal.os.AtomicFile;
     36 
     37 import java.lang.reflect.Constructor;
     38 import java.io.File;
     39 import java.io.FileOutputStream;
     40 import java.io.IOException;
     41 import java.security.PublicKey;
     42 import java.util.ArrayList;
     43 import java.util.List;
     44 
     45 public class PackageManagerSettingsTests extends AndroidTestCase {
     46     private static final String PACKAGE_NAME_2 = "com.google.app2";
     47     private static final String PACKAGE_NAME_3 = "com.android.app3";
     48     private static final String PACKAGE_NAME_1 = "com.google.app1";
     49     private static final boolean localLOGV = true;
     50     public static final String TAG = "PackageManagerSettingsTests";
     51     protected final String PREFIX = "android.content.pm";
     52 
     53     private @NonNull List<UserInfo> createFakeUsers() {
     54         ArrayList<UserInfo> users = new ArrayList<>();
     55         users.add(new UserInfo(UserHandle.USER_SYSTEM, "test user", UserInfo.FLAG_INITIALIZED));
     56         return users;
     57     }
     58 
     59     private void writeFile(File file, byte[] data) {
     60         file.mkdirs();
     61         try {
     62             AtomicFile aFile = new AtomicFile(file);
     63             FileOutputStream fos = aFile.startWrite();
     64             fos.write(data);
     65             aFile.finishWrite(fos);
     66         } catch (IOException ioe) {
     67             Log.e(TAG, "Cannot write file " + file.getPath());
     68         }
     69     }
     70 
     71     private void writePackagesXml() {
     72         writeFile(new File(getContext().getFilesDir(), "system/packages.xml"),
     73                 ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
     74                 + "<packages>"
     75                 + "<last-platform-version internal=\"15\" external=\"0\" fingerprint=\"foo\" />"
     76                 + "<permission-trees>"
     77                 + "<item name=\"com.google.android.permtree\" package=\"com.google.android.permpackage\" />"
     78                 + "</permission-trees>"
     79                 + "<permissions>"
     80                 + "<item name=\"android.permission.WRITE_CALL_LOG\" package=\"android\" protection=\"1\" />"
     81                 + "<item name=\"android.permission.ASEC_ACCESS\" package=\"android\" protection=\"2\" />"
     82                 + "<item name=\"android.permission.ACCESS_WIMAX_STATE\" package=\"android\" />"
     83                 + "<item name=\"android.permission.REBOOT\" package=\"android\" protection=\"18\" />"
     84                 + "</permissions>"
     85                 + "<package name=\"com.google.app1\" codePath=\"/system/app/app1.apk\" nativeLibraryPath=\"/data/data/com.google.app1/lib\" flags=\"1\" ft=\"1360e2caa70\" it=\"135f2f80d08\" ut=\"1360e2caa70\" version=\"1109\" sharedUserId=\"11000\">"
     86                 + "<sigs count=\"1\">"
     87                 + "<cert index=\"0\" key=\"" + KeySetStrings.ctsKeySetCertA + "\" />"
     88                 + "</sigs>"
     89                 + "<proper-signing-keyset identifier=\"1\" />"
     90                 + "</package>"
     91                 + "<package name=\"com.google.app2\" codePath=\"/system/app/app2.apk\" nativeLibraryPath=\"/data/data/com.google.app2/lib\" flags=\"1\" ft=\"1360e578718\" it=\"135f2f80d08\" ut=\"1360e578718\" version=\"15\" enabled=\"3\" userId=\"11001\">"
     92                 + "<sigs count=\"1\">"
     93                 + "<cert index=\"0\" />"
     94                 + "</sigs>"
     95                 + "<proper-signing-keyset identifier=\"1\" />"
     96                 + "<defined-keyset alias=\"AB\" identifier=\"4\" />"
     97                 + "</package>"
     98                 + "<package name=\"com.android.app3\" codePath=\"/system/app/app3.apk\" nativeLibraryPath=\"/data/data/com.android.app3/lib\" flags=\"1\" ft=\"1360e577b60\" it=\"135f2f80d08\" ut=\"1360e577b60\" version=\"15\" userId=\"11030\">"
     99                 + "<sigs count=\"1\">"
    100                 + "<cert index=\"1\" key=\"" + KeySetStrings.ctsKeySetCertB + "\" />"
    101                 + "</sigs>"
    102                 + "<proper-signing-keyset identifier=\"2\" />"
    103                 + "<upgrade-keyset identifier=\"3\" />"
    104                 + "<defined-keyset alias=\"C\" identifier=\"3\" />"
    105                 + "</package>"
    106                 + "<shared-user name=\"com.android.shared1\" userId=\"11000\">"
    107                 + "<sigs count=\"1\">"
    108                 + "<cert index=\"1\" />"
    109                 + "</sigs>"
    110                 + "<perms>"
    111                 + "<item name=\"android.permission.REBOOT\" />"
    112                 + "</perms>"
    113                 + "</shared-user>"
    114                 + "<keyset-settings version=\"1\">"
    115                 + "<keys>"
    116                 + "<public-key identifier=\"1\" value=\"" + KeySetStrings.ctsKeySetPublicKeyA + "\" />"
    117                 + "<public-key identifier=\"2\" value=\"" + KeySetStrings.ctsKeySetPublicKeyB + "\" />"
    118                 + "<public-key identifier=\"3\" value=\"" + KeySetStrings.ctsKeySetPublicKeyC + "\" />"
    119                 + "</keys>"
    120                 + "<keysets>"
    121                 + "<keyset identifier=\"1\">"
    122                 + "<key-id identifier=\"1\" />"
    123                 + "</keyset>"
    124                 + "<keyset identifier=\"2\">"
    125                 + "<key-id identifier=\"2\" />"
    126                 + "</keyset>"
    127                 + "<keyset identifier=\"3\">"
    128                 + "<key-id identifier=\"3\" />"
    129                 + "</keyset>"
    130                 + "<keyset identifier=\"4\">"
    131                 + "<key-id identifier=\"1\" />"
    132                 + "<key-id identifier=\"2\" />"
    133                 + "</keyset>"
    134                 + "</keysets>"
    135                 + "<lastIssuedKeyId value=\"3\" />"
    136                 + "<lastIssuedKeySetId value=\"4\" />"
    137                 + "</keyset-settings>"
    138                 + "</packages>").getBytes());
    139     }
    140 
    141     private void writeStoppedPackagesXml() {
    142         writeFile(new File(getContext().getFilesDir(), "system/packages-stopped.xml"),
    143                 ( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
    144                 + "<stopped-packages>"
    145                 + "<pkg name=\"com.google.app1\" nl=\"1\" />"
    146                 + "<pkg name=\"com.android.app3\" nl=\"1\" />"
    147                 + "</stopped-packages>")
    148                 .getBytes());
    149     }
    150 
    151     private void writePackagesList() {
    152         writeFile(new File(getContext().getFilesDir(), "system/packages.list"),
    153                 ( "com.google.app1 11000 0 /data/data/com.google.app1 seinfo1"
    154                 + "com.google.app2 11001 0 /data/data/com.google.app2 seinfo2"
    155                 + "com.android.app3 11030 0 /data/data/com.android.app3 seinfo3")
    156                 .getBytes());
    157     }
    158 
    159     private void deleteSystemFolder() {
    160         File systemFolder = new File(getContext().getFilesDir(), "system");
    161         deleteFolder(systemFolder);
    162     }
    163 
    164     private static void deleteFolder(File folder) {
    165         File[] files = folder.listFiles();
    166         if (files != null) {
    167             for (File file : files) {
    168                 deleteFolder(file);
    169             }
    170         }
    171         folder.delete();
    172     }
    173 
    174     private void writeOldFiles() {
    175         deleteSystemFolder();
    176         writePackagesXml();
    177         writeStoppedPackagesXml();
    178         writePackagesList();
    179     }
    180 
    181     private void createUserManagerServiceRef() throws ReflectiveOperationException {
    182         Constructor<UserManagerService> umsc =
    183                 UserManagerService.class.getDeclaredConstructor(
    184                         Context.class,
    185                         PackageManagerService.class,
    186                         Object.class,
    187                         Object.class,
    188                         File.class,
    189                         File.class);
    190         umsc.setAccessible(true);
    191         UserManagerService ums = umsc.newInstance(getContext(), null,
    192                 new Object(), new Object(), getContext().getFilesDir(),
    193                 new File(getContext().getFilesDir(), "user"));
    194     }
    195 
    196     private void verifyKeySetMetaData(Settings settings)
    197             throws ReflectiveOperationException, IllegalAccessException {
    198         ArrayMap<String, PackageSetting> packages = settings.mPackages;
    199         KeySetManagerService ksms = settings.mKeySetManagerService;
    200 
    201         /* verify keyset and public key ref counts */
    202         assertEquals(2, KeySetUtils.getKeySetRefCount(ksms, 1));
    203         assertEquals(1, KeySetUtils.getKeySetRefCount(ksms, 2));
    204         assertEquals(1, KeySetUtils.getKeySetRefCount(ksms, 3));
    205         assertEquals(1, KeySetUtils.getKeySetRefCount(ksms, 4));
    206         assertEquals(2, KeySetUtils.getPubKeyRefCount(ksms, 1));
    207         assertEquals(2, KeySetUtils.getPubKeyRefCount(ksms, 2));
    208         assertEquals(1, KeySetUtils.getPubKeyRefCount(ksms, 3));
    209 
    210         /* verify public keys properly read */
    211         PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
    212         PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
    213         PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC);
    214         assertEquals(keyA, KeySetUtils.getPubKey(ksms, 1));
    215         assertEquals(keyB, KeySetUtils.getPubKey(ksms, 2));
    216         assertEquals(keyC, KeySetUtils.getPubKey(ksms, 3));
    217 
    218         /* verify mapping is correct (ks -> pub keys) */
    219         LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(ksms);
    220         ArraySet<Long> mapping = ksMapping.get(1);
    221         assertEquals(1, mapping.size());
    222         assertTrue(mapping.contains(new Long(1)));
    223         mapping = ksMapping.get(2);
    224         assertEquals(1, mapping.size());
    225         assertTrue(mapping.contains(new Long(2)));
    226         mapping = ksMapping.get(3);
    227         assertEquals(1, mapping.size());
    228         assertTrue(mapping.contains(new Long(3)));
    229         mapping = ksMapping.get(4);
    230         assertEquals(2, mapping.size());
    231         assertTrue(mapping.contains(new Long(1)));
    232         assertTrue(mapping.contains(new Long(2)));
    233 
    234         /* verify lastIssuedIds are consistent */
    235         assertEquals(new Long(3), KeySetUtils.getLastIssuedKeyId(ksms));
    236         assertEquals(new Long(4), KeySetUtils.getLastIssuedKeySetId(ksms));
    237 
    238         /* verify packages have been given the appropriat information */
    239         PackageSetting ps = packages.get("com.google.app1");
    240         assertEquals(1, ps.keySetData.getProperSigningKeySet());
    241         ps = packages.get("com.google.app2");
    242         assertEquals(1, ps.keySetData.getProperSigningKeySet());
    243         assertEquals(new Long(4), ps.keySetData.getAliases().get("AB"));
    244         ps = packages.get("com.android.app3");
    245         assertEquals(2, ps.keySetData.getProperSigningKeySet());
    246         assertEquals(new Long(3), ps.keySetData.getAliases().get("C"));
    247         assertEquals(1, ps.keySetData.getUpgradeKeySets().length);
    248         assertEquals(3, ps.keySetData.getUpgradeKeySets()[0]);
    249     }
    250 
    251     /* make sure our initialized keysetmanagerservice metadata matches packages.xml */
    252     public void testReadKeySetSettings()
    253             throws ReflectiveOperationException, IllegalAccessException {
    254 
    255         /* write out files and read */
    256         writeOldFiles();
    257         createUserManagerServiceRef();
    258         Settings settings = new Settings(getContext().getFilesDir(), new Object());
    259         assertEquals(true, settings.readLPw(createFakeUsers()));
    260         verifyKeySetMetaData(settings);
    261     }
    262 
    263     /* read in data, write it out, and read it back in.  Verify same. */
    264     public void testWriteKeySetSettings()
    265             throws ReflectiveOperationException, IllegalAccessException {
    266 
    267         /* write out files and read */
    268         writeOldFiles();
    269         createUserManagerServiceRef();
    270         Settings settings = new Settings(getContext().getFilesDir(), new Object());
    271         assertEquals(true, settings.readLPw(createFakeUsers()));
    272 
    273         /* write out, read back in and verify the same */
    274         settings.writeLPr();
    275         assertEquals(true, settings.readLPw(createFakeUsers()));
    276         verifyKeySetMetaData(settings);
    277     }
    278 
    279     public void testSettingsReadOld() {
    280         // Write the package files and make sure they're parsed properly the first time
    281         writeOldFiles();
    282         Settings settings = new Settings(getContext().getFilesDir(), new Object());
    283         assertEquals(true, settings.readLPw(createFakeUsers()));
    284         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
    285         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
    286 
    287         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
    288         assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(0));
    289         assertEquals(true, ps.getNotLaunched(0));
    290 
    291         ps = settings.peekPackageLPr(PACKAGE_NAME_2);
    292         assertEquals(false, ps.getStopped(0));
    293         assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
    294         assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
    295     }
    296 
    297     public void testNewPackageRestrictionsFile() throws ReflectiveOperationException {
    298 
    299         // Write the package files and make sure they're parsed properly the first time
    300         writeOldFiles();
    301         createUserManagerServiceRef();
    302         Settings settings = new Settings(getContext().getFilesDir(), new Object());
    303         assertEquals(true, settings.readLPw(createFakeUsers()));
    304         settings.writeLPr();
    305 
    306         // Create Settings again to make it read from the new files
    307         settings = new Settings(getContext().getFilesDir(), new Object());
    308         assertEquals(true, settings.readLPw(createFakeUsers()));
    309 
    310         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
    311         assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
    312         assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
    313     }
    314 
    315     public void testEnableDisable() {
    316         // Write the package files and make sure they're parsed properly the first time
    317         writeOldFiles();
    318         Settings settings = new Settings(getContext().getFilesDir(), new Object());
    319         assertEquals(true, settings.readLPw(createFakeUsers()));
    320 
    321         // Enable/Disable a package
    322         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
    323         ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null);
    324         ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null);
    325         assertEquals(COMPONENT_ENABLED_STATE_DISABLED, ps.getEnabled(0));
    326         assertEquals(COMPONENT_ENABLED_STATE_ENABLED, ps.getEnabled(1));
    327 
    328         // Enable/Disable a component
    329         ArraySet<String> components = new ArraySet<String>();
    330         String component1 = PACKAGE_NAME_1 + "/.Component1";
    331         components.add(component1);
    332         ps.setDisabledComponents(components, 0);
    333         ArraySet<String> componentsDisabled = ps.getDisabledComponents(0);
    334         assertEquals(1, componentsDisabled.size());
    335         assertEquals(component1, componentsDisabled.toArray()[0]);
    336         boolean hasEnabled =
    337                 ps.getEnabledComponents(0) != null && ps.getEnabledComponents(1).size() > 0;
    338         assertEquals(false, hasEnabled);
    339 
    340         // User 1 should not have any disabled components
    341         boolean hasDisabled =
    342                 ps.getDisabledComponents(1) != null && ps.getDisabledComponents(1).size() > 0;
    343         assertEquals(false, hasDisabled);
    344         ps.setEnabledComponents(components, 1);
    345         assertEquals(1, ps.getEnabledComponents(1).size());
    346         hasEnabled = ps.getEnabledComponents(0) != null && ps.getEnabledComponents(0).size() > 0;
    347         assertEquals(false, hasEnabled);
    348     }
    349 }
    350