Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2006 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 android.content.pm;
     18 
     19 import static android.system.OsConstants.S_IFDIR;
     20 import static android.system.OsConstants.S_IFMT;
     21 import static android.system.OsConstants.S_IRGRP;
     22 import static android.system.OsConstants.S_IROTH;
     23 import static android.system.OsConstants.S_IRWXU;
     24 import static android.system.OsConstants.S_ISDIR;
     25 import static android.system.OsConstants.S_IXGRP;
     26 import static android.system.OsConstants.S_IXOTH;
     27 
     28 import android.content.BroadcastReceiver;
     29 import android.content.Context;
     30 import android.content.IIntentReceiver;
     31 import android.content.IIntentSender;
     32 import android.content.Intent;
     33 import android.content.IntentFilter;
     34 import android.content.IntentSender;
     35 import android.content.pm.PackageInstaller.SessionParams;
     36 import android.content.pm.PackageManager.NameNotFoundException;
     37 import android.content.pm.PackageParser.PackageParserException;
     38 import android.content.res.Resources;
     39 import android.content.res.Resources.NotFoundException;
     40 import android.net.Uri;
     41 import android.os.Binder;
     42 import android.os.Build;
     43 import android.os.Bundle;
     44 import android.os.Environment;
     45 import android.os.FileUtils;
     46 import android.os.IBinder;
     47 import android.os.Process;
     48 import android.os.RemoteException;
     49 import android.os.StatFs;
     50 import android.os.SystemClock;
     51 import android.provider.Settings;
     52 import android.provider.Settings.SettingNotFoundException;
     53 import android.system.ErrnoException;
     54 import android.system.Os;
     55 import android.system.StructStat;
     56 import android.test.AndroidTestCase;
     57 import android.test.suitebuilder.annotation.LargeTest;
     58 import android.test.suitebuilder.annotation.SmallTest;
     59 import android.test.suitebuilder.annotation.Suppress;
     60 import android.util.Log;
     61 
     62 import com.android.frameworks.coretests.R;
     63 import com.android.internal.content.PackageHelper;
     64 
     65 import dalvik.system.VMRuntime;
     66 
     67 import libcore.io.IoUtils;
     68 
     69 import java.io.File;
     70 import java.io.FileInputStream;
     71 import java.io.IOException;
     72 import java.io.InputStream;
     73 import java.io.OutputStream;
     74 import java.nio.file.Files;
     75 import java.nio.file.Paths;
     76 import java.nio.file.StandardCopyOption;
     77 import java.util.HashSet;
     78 import java.util.List;
     79 import java.util.Set;
     80 import java.util.concurrent.CountDownLatch;
     81 import java.util.concurrent.SynchronousQueue;
     82 import java.util.concurrent.TimeUnit;
     83 
     84 public class PackageManagerTests extends AndroidTestCase {
     85     private static final boolean localLOGV = true;
     86 
     87     public static final String TAG = "PackageManagerTests";
     88 
     89     public static final long MAX_WAIT_TIME = 25 * 1000;
     90 
     91     public static final long WAIT_TIME_INCR = 5 * 1000;
     92 
     93     private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec";
     94 
     95     private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
     96 
     97     private static final int APP_INSTALL_DEVICE = PackageHelper.APP_INSTALL_INTERNAL;
     98 
     99     private static final int APP_INSTALL_SDCARD = PackageHelper.APP_INSTALL_EXTERNAL;
    100 
    101     void failStr(String errMsg) {
    102         Log.w(TAG, "errMsg=" + errMsg);
    103         fail(errMsg);
    104     }
    105 
    106     void failStr(Exception e) {
    107         failStr(e.getMessage());
    108     }
    109 
    110     private abstract static class GenericReceiver extends BroadcastReceiver {
    111         private boolean doneFlag = false;
    112 
    113         boolean received = false;
    114 
    115         Intent intent;
    116 
    117         IntentFilter filter;
    118 
    119         abstract boolean notifyNow(Intent intent);
    120 
    121         @Override
    122         public void onReceive(Context context, Intent intent) {
    123             if (notifyNow(intent)) {
    124                 synchronized (this) {
    125                     received = true;
    126                     doneFlag = true;
    127                     this.intent = intent;
    128                     notifyAll();
    129                 }
    130             }
    131         }
    132 
    133         public boolean isDone() {
    134             return doneFlag;
    135         }
    136 
    137         public void setFilter(IntentFilter filter) {
    138             this.filter = filter;
    139         }
    140     }
    141 
    142     private static class InstallReceiver extends GenericReceiver {
    143         String pkgName;
    144 
    145         InstallReceiver(String pkgName) {
    146             this.pkgName = pkgName;
    147             IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
    148             filter.addDataScheme("package");
    149             super.setFilter(filter);
    150         }
    151 
    152         public boolean notifyNow(Intent intent) {
    153             String action = intent.getAction();
    154             if (!Intent.ACTION_PACKAGE_ADDED.equals(action)) {
    155                 return false;
    156             }
    157             Uri data = intent.getData();
    158             String installedPkg = data.getEncodedSchemeSpecificPart();
    159             if (pkgName.equals(installedPkg)) {
    160                 return true;
    161             }
    162             return false;
    163         }
    164     }
    165 
    166     private static class LocalIntentReceiver {
    167         private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
    168 
    169         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
    170             @Override
    171             public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
    172                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
    173                 try {
    174                     mResult.offer(intent, 5, TimeUnit.SECONDS);
    175                 } catch (InterruptedException e) {
    176                     throw new RuntimeException(e);
    177                 }
    178             }
    179         };
    180 
    181         public IntentSender getIntentSender() {
    182             return new IntentSender((IIntentSender) mLocalSender);
    183         }
    184 
    185         public Intent getResult() {
    186             try {
    187                 return mResult.take();
    188             } catch (InterruptedException e) {
    189                 throw new RuntimeException(e);
    190             }
    191         }
    192     }
    193 
    194     private PackageManager getPm() {
    195         return mContext.getPackageManager();
    196     }
    197 
    198     private PackageInstaller getPi() {
    199         return getPm().getPackageInstaller();
    200     }
    201 
    202     private void writeSplitToInstallSession(PackageInstaller.Session session, String inPath,
    203             String splitName) throws RemoteException {
    204         long sizeBytes = 0;
    205         final File file = new File(inPath);
    206         if (file.isFile()) {
    207             sizeBytes = file.length();
    208         } else {
    209             return;
    210         }
    211 
    212         InputStream in = null;
    213         OutputStream out = null;
    214         try {
    215             in = new FileInputStream(inPath);
    216             out = session.openWrite(splitName, 0, sizeBytes);
    217 
    218             int total = 0;
    219             byte[] buffer = new byte[65536];
    220             int c;
    221             while ((c = in.read(buffer)) != -1) {
    222                 total += c;
    223                 out.write(buffer, 0, c);
    224             }
    225             session.fsync(out);
    226         } catch (IOException e) {
    227             fail("Error: failed to write; " + e.getMessage());
    228         } finally {
    229             IoUtils.closeQuietly(out);
    230             IoUtils.closeQuietly(in);
    231             IoUtils.closeQuietly(session);
    232         }
    233     }
    234 
    235     private void invokeInstallPackage(Uri packageUri, int flags, GenericReceiver receiver,
    236             boolean shouldSucceed) {
    237         mContext.registerReceiver(receiver, receiver.filter);
    238         synchronized (receiver) {
    239             final String inPath = packageUri.getPath();
    240             PackageInstaller.Session session = null;
    241             try {
    242                 final SessionParams sessionParams =
    243                         new SessionParams(SessionParams.MODE_FULL_INSTALL);
    244                 sessionParams.installFlags = flags;
    245                 final int sessionId = getPi().createSession(sessionParams);
    246                 session = getPi().openSession(sessionId);
    247                 writeSplitToInstallSession(session, inPath, "base.apk");
    248                 final LocalIntentReceiver localReceiver = new LocalIntentReceiver();
    249                 session.commit(localReceiver.getIntentSender());
    250                 final Intent result = localReceiver.getResult();
    251                 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
    252                         PackageInstaller.STATUS_FAILURE);
    253                 if (shouldSucceed) {
    254                     if (status != PackageInstaller.STATUS_SUCCESS) {
    255                         fail("Installation should have succeeded, but got code " + status);
    256                     }
    257                 } else {
    258                     if (status == PackageInstaller.STATUS_SUCCESS) {
    259                         fail("Installation should have failed");
    260                     }
    261                     // We'll never get a broadcast since the package failed to install
    262                     return;
    263                 }
    264                 // Verify we received the broadcast
    265                 long waitTime = 0;
    266                 while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
    267                     try {
    268                         receiver.wait(WAIT_TIME_INCR);
    269                         waitTime += WAIT_TIME_INCR;
    270                     } catch (InterruptedException e) {
    271                         Log.i(TAG, "Interrupted during sleep", e);
    272                     }
    273                 }
    274                 if (!receiver.isDone()) {
    275                     fail("Timed out waiting for PACKAGE_ADDED notification");
    276                 }
    277             } catch (IllegalArgumentException | IOException | RemoteException e) {
    278                 Log.w(TAG, "Failed to install package; path=" + inPath, e);
    279                 fail("Failed to install package; path=" + inPath + ", e=" + e);
    280             } finally {
    281                 IoUtils.closeQuietly(session);
    282                 mContext.unregisterReceiver(receiver);
    283             }
    284         }
    285     }
    286 
    287     private void invokeInstallPackageFail(Uri packageUri, int flags, int expectedResult) {
    288         final String inPath = packageUri.getPath();
    289         PackageInstaller.Session session = null;
    290         try {
    291             final SessionParams sessionParams =
    292                     new SessionParams(SessionParams.MODE_FULL_INSTALL);
    293             sessionParams.installFlags = flags;
    294             final int sessionId = getPi().createSession(sessionParams);
    295             session = getPi().openSession(sessionId);
    296             writeSplitToInstallSession(session, inPath, "base.apk");
    297             final LocalIntentReceiver localReceiver = new LocalIntentReceiver();
    298             session.commit(localReceiver.getIntentSender());
    299             final Intent result = localReceiver.getResult();
    300             final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
    301                     PackageInstaller.STATUS_SUCCESS);
    302             assertEquals(expectedResult, status);
    303         } catch (IllegalArgumentException | IOException | RemoteException e) {
    304             Log.w(TAG, "Failed to install package; path=" + inPath, e);
    305             fail("Failed to install package; path=" + inPath + ", e=" + e);
    306         } finally {
    307             IoUtils.closeQuietly(session);
    308         }
    309     }
    310 
    311     private Uri getInstallablePackage(int fileResId, File outFile) {
    312         Resources res = mContext.getResources();
    313         InputStream is = null;
    314         try {
    315             is = res.openRawResource(fileResId);
    316         } catch (NotFoundException e) {
    317             failStr("Failed to load resource with id: " + fileResId);
    318         }
    319         FileUtils.setPermissions(outFile.getPath(),
    320                 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO,
    321                 -1, -1);
    322         assertTrue(FileUtils.copyToFile(is, outFile));
    323         FileUtils.setPermissions(outFile.getPath(),
    324                 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO,
    325                 -1, -1);
    326         return Uri.fromFile(outFile);
    327     }
    328 
    329     private PackageParser.Package parsePackage(Uri packageURI) throws PackageParserException {
    330         final String archiveFilePath = packageURI.getPath();
    331         PackageParser packageParser = new PackageParser();
    332         File sourceFile = new File(archiveFilePath);
    333         PackageParser.Package pkg = packageParser.parseMonolithicPackage(sourceFile, 0);
    334         packageParser = null;
    335         return pkg;
    336     }
    337 
    338     private boolean checkSd(long pkgLen) {
    339         String status = Environment.getExternalStorageState();
    340         if (!status.equals(Environment.MEDIA_MOUNTED)) {
    341             return false;
    342         }
    343         long sdSize = -1;
    344         StatFs sdStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
    345         sdSize = (long) sdStats.getAvailableBlocks() * (long) sdStats.getBlockSize();
    346         // TODO check for thresholds here
    347         return pkgLen <= sdSize;
    348 
    349     }
    350 
    351     private boolean checkInt(long pkgLen) {
    352         StatFs intStats = new StatFs(Environment.getDataDirectory().getPath());
    353         long intSize = (long) intStats.getBlockCount() * (long) intStats.getBlockSize();
    354         long iSize = (long) intStats.getAvailableBlocks() * (long) intStats.getBlockSize();
    355         // TODO check for thresholds here?
    356         return pkgLen <= iSize;
    357     }
    358 
    359     private static final int INSTALL_LOC_INT = 1;
    360 
    361     private static final int INSTALL_LOC_SD = 2;
    362 
    363     private static final int INSTALL_LOC_ERR = -1;
    364 
    365     private int getInstallLoc(int flags, int expInstallLocation, long pkgLen) {
    366         // Flags explicitly over ride everything else.
    367         if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
    368             return INSTALL_LOC_SD;
    369         } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
    370             return INSTALL_LOC_INT;
    371         }
    372         // Manifest option takes precedence next
    373         if (expInstallLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
    374             if (checkSd(pkgLen)) {
    375                 return INSTALL_LOC_SD;
    376             }
    377             if (checkInt(pkgLen)) {
    378                 return INSTALL_LOC_INT;
    379             }
    380             return INSTALL_LOC_ERR;
    381         }
    382         if (expInstallLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
    383             if (checkInt(pkgLen)) {
    384                 return INSTALL_LOC_INT;
    385             }
    386             return INSTALL_LOC_ERR;
    387         }
    388         if (expInstallLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
    389             // Check for free memory internally
    390             if (checkInt(pkgLen)) {
    391                 return INSTALL_LOC_INT;
    392             }
    393             // Check for free memory externally
    394             if (checkSd(pkgLen)) {
    395                 return INSTALL_LOC_SD;
    396             }
    397             return INSTALL_LOC_ERR;
    398         }
    399         // Check for settings preference.
    400         boolean checkSd = false;
    401         int userPref = getDefaultInstallLoc();
    402         if (userPref == APP_INSTALL_DEVICE) {
    403             if (checkInt(pkgLen)) {
    404                 return INSTALL_LOC_INT;
    405             }
    406             return INSTALL_LOC_ERR;
    407         } else if (userPref == APP_INSTALL_SDCARD) {
    408             if (checkSd(pkgLen)) {
    409                 return INSTALL_LOC_SD;
    410             }
    411             return INSTALL_LOC_ERR;
    412         }
    413         // Default system policy for apps with no manifest option specified.
    414         // Check for free memory internally
    415         if (checkInt(pkgLen)) {
    416             return INSTALL_LOC_INT;
    417         }
    418         return INSTALL_LOC_ERR;
    419     }
    420 
    421     private void assertInstall(PackageParser.Package pkg, int flags, int expInstallLocation) {
    422         try {
    423             String pkgName = pkg.packageName;
    424             ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
    425             assertNotNull(info);
    426             assertEquals(pkgName, info.packageName);
    427             File dataDir = Environment.getDataDirectory();
    428             String appInstallPath = new File(dataDir, "app").getPath();
    429             String drmInstallPath = new File(dataDir, "app-private").getPath();
    430             File srcDir = new File(info.sourceDir);
    431             String srcPath = srcDir.getParentFile().getParent();
    432             File publicSrcDir = new File(info.publicSourceDir);
    433             String publicSrcPath = publicSrcDir.getParentFile().getParent();
    434             long pkgLen = new File(info.sourceDir).length();
    435             String expectedLibPath = new File(new File(info.sourceDir).getParentFile(), "lib")
    436                     .getPath();
    437 
    438             int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen);
    439             if (rLoc == INSTALL_LOC_INT) {
    440                 assertFalse(
    441                         (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
    442                 assertEquals(appInstallPath, srcPath);
    443                 assertEquals(appInstallPath, publicSrcPath);
    444                 assertStartsWith("Native library should point to shared lib directory",
    445                         expectedLibPath, info.nativeLibraryDir);
    446                 assertDirOwnerGroupPermsIfExists(
    447                         "Native library directory should be owned by system:system and 0755",
    448                         Process.SYSTEM_UID, Process.SYSTEM_UID,
    449                         S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
    450                         info.nativeLibraryDir);
    451                 assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
    452 
    453                 // Make sure the native library dir is not a symlink
    454                 final File nativeLibDir = new File(info.nativeLibraryDir);
    455                 if (nativeLibDir.exists()) {
    456                     try {
    457                         assertEquals("Native library dir should not be a symlink",
    458                                 info.nativeLibraryDir, nativeLibDir.getCanonicalPath());
    459                     } catch (IOException e) {
    460                         fail("Can't read " + nativeLibDir.getPath());
    461                     }
    462                 }
    463             } else if (rLoc == INSTALL_LOC_SD) {
    464                 assertFalse("The application should not be installed forward locked",
    465                         (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
    466                 assertTrue("Application flags (" + info.flags
    467                         + ") should contain FLAG_EXTERNAL_STORAGE",
    468                         (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
    469                 // Might need to check:
    470                 // ((info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0)
    471                 assertStartsWith("The APK path should point to the ASEC",
    472                         SECURE_CONTAINERS_PREFIX, srcPath);
    473                 assertStartsWith("The public APK path should point to the ASEC",
    474                         SECURE_CONTAINERS_PREFIX, publicSrcPath);
    475                 assertStartsWith("The native library path should point to the ASEC",
    476                         SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
    477 
    478                 // Make sure the native library in /data/data/<app>/lib is a
    479                 // symlink to the ASEC
    480                 final File nativeLibSymLink = new File(info.dataDir, "lib");
    481                 assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(),
    482                         nativeLibSymLink.exists());
    483                 try {
    484                     assertEquals(nativeLibSymLink.getPath() + " should be a symlink to "
    485                             + info.nativeLibraryDir, info.nativeLibraryDir,
    486                             nativeLibSymLink.getCanonicalPath());
    487                 } catch (IOException e) {
    488                     fail("Can't read " + nativeLibSymLink.getPath());
    489                 }
    490             } else {
    491                 // TODO handle error. Install should have failed.
    492                 fail("Install should have failed");
    493             }
    494         } catch (NameNotFoundException e) {
    495             failStr("failed with exception : " + e);
    496         }
    497     }
    498 
    499     private void assertDirOwnerGroupPermsIfExists(String reason, int uid, int gid, int perms,
    500             String path) {
    501         if (!new File(path).exists()) {
    502             return;
    503         }
    504 
    505         final StructStat stat;
    506         try {
    507             stat = Os.lstat(path);
    508         } catch (ErrnoException e) {
    509             throw new AssertionError(reason + "\n" + "Got: " + path + " does not exist");
    510         }
    511 
    512         StringBuilder sb = new StringBuilder();
    513 
    514         if (!S_ISDIR(stat.st_mode)) {
    515             sb.append("\nExpected type: ");
    516             sb.append(S_IFDIR);
    517             sb.append("\ngot type: ");
    518             sb.append((stat.st_mode & S_IFMT));
    519         }
    520 
    521         if (stat.st_uid != uid) {
    522             sb.append("\nExpected owner: ");
    523             sb.append(uid);
    524             sb.append("\nGot owner: ");
    525             sb.append(stat.st_uid);
    526         }
    527 
    528         if (stat.st_gid != gid) {
    529             sb.append("\nExpected group: ");
    530             sb.append(gid);
    531             sb.append("\nGot group: ");
    532             sb.append(stat.st_gid);
    533         }
    534 
    535         if ((stat.st_mode & ~S_IFMT) != perms) {
    536             sb.append("\nExpected permissions: ");
    537             sb.append(Integer.toOctalString(perms));
    538             sb.append("\nGot permissions: ");
    539             sb.append(Integer.toOctalString(stat.st_mode & ~S_IFMT));
    540         }
    541 
    542         if (sb.length() > 0) {
    543             throw new AssertionError(reason + sb.toString());
    544         }
    545     }
    546 
    547     private static void assertStartsWith(String prefix, String actual) {
    548         assertStartsWith("", prefix, actual);
    549     }
    550 
    551     private static void assertStartsWith(String description, String prefix, String actual) {
    552         if (!actual.startsWith(prefix)) {
    553             StringBuilder sb = new StringBuilder(description);
    554             sb.append("\nExpected prefix: ");
    555             sb.append(prefix);
    556             sb.append("\n     got: ");
    557             sb.append(actual);
    558             sb.append('\n');
    559             throw new AssertionError(sb.toString());
    560         }
    561     }
    562 
    563     private void assertNotInstalled(String pkgName) {
    564         try {
    565             ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
    566             fail(pkgName + " shouldnt be installed");
    567         } catch (NameNotFoundException e) {
    568         }
    569     }
    570 
    571     class InstallParams {
    572         Uri packageURI;
    573 
    574         PackageParser.Package pkg;
    575 
    576         InstallParams(String outFileName, int rawResId) throws PackageParserException {
    577             this.pkg = getParsedPackage(outFileName, rawResId);
    578             this.packageURI = Uri.fromFile(new File(pkg.codePath));
    579         }
    580 
    581         InstallParams(PackageParser.Package pkg) {
    582             this.packageURI = Uri.fromFile(new File(pkg.codePath));
    583             this.pkg = pkg;
    584         }
    585 
    586         long getApkSize() {
    587             File file = new File(pkg.codePath);
    588             return file.length();
    589         }
    590     }
    591 
    592     private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp)
    593             throws Exception {
    594         return installFromRawResource("install.apk", R.raw.install, flags, cleanUp, false, -1,
    595                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
    596     }
    597 
    598     static final String PERM_PACKAGE = "package";
    599 
    600     static final String PERM_DEFINED = "defined";
    601 
    602     static final String PERM_UNDEFINED = "undefined";
    603 
    604     static final String PERM_USED = "used";
    605 
    606     static final String PERM_NOTUSED = "notused";
    607 
    608     private void assertPermissions(String[] cmds) {
    609         final PackageManager pm = getPm();
    610         String pkg = null;
    611         PackageInfo pkgInfo = null;
    612         String mode = PERM_DEFINED;
    613         int i = 0;
    614         while (i < cmds.length) {
    615             String cmd = cmds[i++];
    616             if (cmd == PERM_PACKAGE) {
    617                 pkg = cmds[i++];
    618                 try {
    619                     pkgInfo = pm.getPackageInfo(pkg,
    620                             PackageManager.GET_PERMISSIONS
    621                             | PackageManager.MATCH_UNINSTALLED_PACKAGES);
    622                 } catch (NameNotFoundException e) {
    623                     pkgInfo = null;
    624                 }
    625             } else if (cmd == PERM_DEFINED || cmd == PERM_UNDEFINED
    626                     || cmd == PERM_USED || cmd == PERM_NOTUSED) {
    627                 mode = cmds[i++];
    628             } else {
    629                 if (mode == PERM_DEFINED) {
    630                     try {
    631                         PermissionInfo pi = pm.getPermissionInfo(cmd, 0);
    632                         assertNotNull(pi);
    633                         assertEquals(pi.packageName, pkg);
    634                         assertEquals(pi.name, cmd);
    635                         assertNotNull(pkgInfo);
    636                         boolean found = false;
    637                         for (int j = 0; j < pkgInfo.permissions.length && !found; j++) {
    638                             if (pkgInfo.permissions[j].name.equals(cmd)) {
    639                                 found = true;
    640                             }
    641                         }
    642                         if (!found) {
    643                             fail("Permission not found: " + cmd);
    644                         }
    645                     } catch (NameNotFoundException e) {
    646                         throw new RuntimeException(e);
    647                     }
    648                 } else if (mode == PERM_UNDEFINED) {
    649                     try {
    650                         pm.getPermissionInfo(cmd, 0);
    651                         throw new RuntimeException("Permission exists: " + cmd);
    652                     } catch (NameNotFoundException e) {
    653                     }
    654                     if (pkgInfo != null) {
    655                         boolean found = false;
    656                         for (int j = 0; j < pkgInfo.permissions.length && !found; j++) {
    657                             if (pkgInfo.permissions[j].name.equals(cmd)) {
    658                                 found = true;
    659                             }
    660                         }
    661                         if (found) {
    662                             fail("Permission still exists: " + cmd);
    663                         }
    664                     }
    665                 } else if (mode == PERM_USED || mode == PERM_NOTUSED) {
    666                     boolean found = false;
    667                     for (int j = 0; j < pkgInfo.requestedPermissions.length && !found; j++) {
    668                         if (pkgInfo.requestedPermissions[j].equals(cmd)) {
    669                             found = true;
    670                         }
    671                     }
    672                     if (!found) {
    673                         fail("Permission not requested: " + cmd);
    674                     }
    675                     if (mode == PERM_USED) {
    676                         if (pm.checkPermission(cmd, pkg) != PackageManager.PERMISSION_GRANTED) {
    677                             fail("Permission not granted: " + cmd);
    678                         }
    679                     } else {
    680                         if (pm.checkPermission(cmd, pkg) != PackageManager.PERMISSION_DENIED) {
    681                             fail("Permission granted: " + cmd);
    682                         }
    683                     }
    684                 }
    685             }
    686         }
    687     }
    688 
    689     private PackageParser.Package getParsedPackage(String outFileName, int rawResId)
    690             throws PackageParserException {
    691         PackageManager pm = mContext.getPackageManager();
    692         File filesDir = mContext.getFilesDir();
    693         File outFile = new File(filesDir, outFileName);
    694         Uri packageURI = getInstallablePackage(rawResId, outFile);
    695         PackageParser.Package pkg = parsePackage(packageURI);
    696         return pkg;
    697     }
    698 
    699     /*
    700      * Utility function that reads a apk bundled as a raw resource
    701      * copies it into own data directory and invokes
    702      * PackageManager api to install it.
    703      */
    704     private void installFromRawResource(InstallParams ip, int flags, boolean cleanUp, boolean fail,
    705             int result, int expInstallLocation) throws Exception {
    706         PackageManager pm = mContext.getPackageManager();
    707         PackageParser.Package pkg = ip.pkg;
    708         Uri packageURI = ip.packageURI;
    709         if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) == 0) {
    710             // Make sure the package doesn't exist
    711             try {
    712                 ApplicationInfo appInfo = pm.getApplicationInfo(pkg.packageName,
    713                         PackageManager.MATCH_UNINSTALLED_PACKAGES);
    714                 GenericReceiver receiver = new DeleteReceiver(pkg.packageName);
    715                 invokeDeletePackage(pkg.packageName, 0, receiver);
    716             } catch (IllegalArgumentException | NameNotFoundException e) {
    717             }
    718         }
    719         try {
    720             if (fail) {
    721                 invokeInstallPackageFail(packageURI, flags, result);
    722                 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) == 0) {
    723                     assertNotInstalled(pkg.packageName);
    724                 }
    725             } else {
    726                 InstallReceiver receiver = new InstallReceiver(pkg.packageName);
    727                 invokeInstallPackage(packageURI, flags, receiver, true);
    728                 // Verify installed information
    729                 assertInstall(pkg, flags, expInstallLocation);
    730             }
    731         } finally {
    732             if (cleanUp) {
    733                 cleanUpInstall(ip);
    734             }
    735         }
    736     }
    737 
    738     /*
    739      * Utility function that reads a apk bundled as a raw resource
    740      * copies it into own data directory and invokes
    741      * PackageManager api to install it.
    742      */
    743     private InstallParams installFromRawResource(String outFileName, int rawResId, int flags,
    744             boolean cleanUp, boolean fail, int result, int expInstallLocation) throws Exception {
    745         InstallParams ip = new InstallParams(outFileName, rawResId);
    746         installFromRawResource(ip, flags, cleanUp, fail, result, expInstallLocation);
    747         return ip;
    748     }
    749 
    750     @LargeTest
    751     public void testInstallNormalInternal() throws Exception {
    752         sampleInstallFromRawResource(0, true);
    753     }
    754 
    755     /* ------------------------- Test replacing packages -------------- */
    756     class ReplaceReceiver extends GenericReceiver {
    757         String pkgName;
    758 
    759         final static int INVALID = -1;
    760 
    761         final static int REMOVED = 1;
    762 
    763         final static int ADDED = 2;
    764 
    765         final static int REPLACED = 3;
    766 
    767         int removed = INVALID;
    768 
    769         // for updated system apps only
    770         boolean update = false;
    771 
    772         ReplaceReceiver(String pkgName) {
    773             this.pkgName = pkgName;
    774             filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
    775             filter.addAction(Intent.ACTION_PACKAGE_ADDED);
    776             if (update) {
    777                 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
    778             }
    779             filter.addDataScheme("package");
    780             super.setFilter(filter);
    781         }
    782 
    783         public boolean notifyNow(Intent intent) {
    784             String action = intent.getAction();
    785             Uri data = intent.getData();
    786             String installedPkg = data.getEncodedSchemeSpecificPart();
    787             if (pkgName == null || !pkgName.equals(installedPkg)) {
    788                 return false;
    789             }
    790             if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
    791                 removed = REMOVED;
    792             } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
    793                 if (removed != REMOVED) {
    794                     return false;
    795                 }
    796                 boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
    797                 if (!replacing) {
    798                     return false;
    799                 }
    800                 removed = ADDED;
    801                 if (!update) {
    802                     return true;
    803                 }
    804             } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
    805                 if (removed != ADDED) {
    806                     return false;
    807                 }
    808                 removed = REPLACED;
    809                 return true;
    810             }
    811             return false;
    812         }
    813     }
    814 
    815     /*
    816      * Utility function that reads a apk bundled as a raw resource
    817      * copies it into own data directory and invokes
    818      * PackageManager api to install first and then replace it
    819      * again.
    820      */
    821     private void sampleReplaceFromRawResource(int flags) throws Exception {
    822         InstallParams ip = sampleInstallFromRawResource(flags, false);
    823         boolean replace = ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0);
    824         Log.i(TAG, "replace=" + replace);
    825         GenericReceiver receiver;
    826         if (replace) {
    827             receiver = new ReplaceReceiver(ip.pkg.packageName);
    828             Log.i(TAG, "Creating replaceReceiver");
    829         } else {
    830             receiver = new InstallReceiver(ip.pkg.packageName);
    831         }
    832         try {
    833             invokeInstallPackage(ip.packageURI, flags, receiver, true);
    834             if (replace) {
    835                 assertInstall(ip.pkg, flags, ip.pkg.installLocation);
    836             }
    837         } finally {
    838             cleanUpInstall(ip);
    839         }
    840     }
    841 
    842     @LargeTest
    843     public void testReplaceFlagDoesNotNeedToBeSet() throws Exception {
    844         sampleReplaceFromRawResource(0);
    845     }
    846 
    847     @LargeTest
    848     public void testReplaceFailSdcard() throws Exception {
    849         // Do not run on devices with emulated external storage.
    850         if (Environment.isExternalStorageEmulated()) {
    851             return;
    852         }
    853 
    854         sampleReplaceFromRawResource(PackageManager.INSTALL_EXTERNAL);
    855     }
    856 
    857     @LargeTest
    858     public void testReplaceNormalInternal() throws Exception {
    859         sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING);
    860     }
    861 
    862     @LargeTest
    863     public void testReplaceSdcard() throws Exception {
    864         // Do not run on devices with emulated external storage.
    865         if (Environment.isExternalStorageEmulated()) {
    866             return;
    867         }
    868 
    869         sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING
    870                 | PackageManager.INSTALL_EXTERNAL);
    871     }
    872 
    873     /* -------------- Delete tests --- */
    874     private static class DeleteObserver extends IPackageDeleteObserver.Stub {
    875         private CountDownLatch mLatch = new CountDownLatch(1);
    876 
    877         private int mReturnCode;
    878 
    879         private final String mPackageName;
    880 
    881         private String mObservedPackage;
    882 
    883         public DeleteObserver(String packageName) {
    884             mPackageName = packageName;
    885         }
    886 
    887         public boolean isSuccessful() {
    888             return mReturnCode == PackageManager.DELETE_SUCCEEDED;
    889         }
    890 
    891         public void packageDeleted(String packageName, int returnCode) throws RemoteException {
    892             mObservedPackage = packageName;
    893 
    894             mReturnCode = returnCode;
    895 
    896             mLatch.countDown();
    897         }
    898 
    899         public void waitForCompletion(long timeoutMillis) {
    900             final long deadline = SystemClock.uptimeMillis() + timeoutMillis;
    901 
    902             long waitTime = timeoutMillis;
    903             while (waitTime > 0) {
    904                 try {
    905                     boolean done = mLatch.await(waitTime, TimeUnit.MILLISECONDS);
    906                     if (done) {
    907                         assertEquals(mPackageName, mObservedPackage);
    908                         return;
    909                     }
    910                 } catch (InterruptedException e) {
    911                     // TODO Auto-generated catch block
    912                     e.printStackTrace();
    913                 }
    914                 waitTime = deadline - SystemClock.uptimeMillis();
    915             }
    916 
    917             throw new AssertionError("Timeout waiting for package deletion");
    918         }
    919     }
    920 
    921     class DeleteReceiver extends GenericReceiver {
    922         String pkgName;
    923 
    924         DeleteReceiver(String pkgName) {
    925             this.pkgName = pkgName;
    926             IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
    927             filter.addDataScheme("package");
    928             super.setFilter(filter);
    929         }
    930 
    931         public boolean notifyNow(Intent intent) {
    932             String action = intent.getAction();
    933             if (!Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
    934                 return false;
    935             }
    936             Uri data = intent.getData();
    937             String installedPkg = data.getEncodedSchemeSpecificPart();
    938             if (pkgName.equals(installedPkg)) {
    939                 return true;
    940             }
    941             return false;
    942         }
    943     }
    944 
    945     public boolean invokeDeletePackage(final String pkgName, int flags, GenericReceiver receiver)
    946             throws Exception {
    947         ApplicationInfo info = getPm().getApplicationInfo(pkgName,
    948                 PackageManager.MATCH_UNINSTALLED_PACKAGES);
    949 
    950         mContext.registerReceiver(receiver, receiver.filter);
    951         try {
    952             final LocalIntentReceiver localReceiver = new LocalIntentReceiver();
    953             getPi().uninstall(pkgName,
    954                     flags | PackageManager.DELETE_ALL_USERS,
    955                     localReceiver.getIntentSender());
    956             localReceiver.getResult();
    957 
    958             assertUninstalled(info);
    959 
    960             // Verify we received the broadcast
    961             // TODO replace this with a CountDownLatch
    962             synchronized (receiver) {
    963                 long waitTime = 0;
    964                 while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
    965                     receiver.wait(WAIT_TIME_INCR);
    966                     waitTime += WAIT_TIME_INCR;
    967                 }
    968                 if (!receiver.isDone()) {
    969                     throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
    970                 }
    971             }
    972             return receiver.received;
    973         } finally {
    974             mContext.unregisterReceiver(receiver);
    975         }
    976     }
    977 
    978     private static void assertUninstalled(ApplicationInfo info) throws Exception {
    979         File nativeLibraryFile = new File(info.nativeLibraryDir);
    980         assertFalse("Native library directory " + info.nativeLibraryDir
    981                 + " should be erased", nativeLibraryFile.exists());
    982     }
    983 
    984     public void deleteFromRawResource(int iFlags, int dFlags) throws Exception {
    985         InstallParams ip = sampleInstallFromRawResource(iFlags, false);
    986         boolean retainData = ((dFlags & PackageManager.DELETE_KEEP_DATA) != 0);
    987         GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
    988         try {
    989             assertTrue(invokeDeletePackage(ip.pkg.packageName, dFlags, receiver));
    990             ApplicationInfo info = null;
    991             Log.i(TAG, "okay4");
    992             try {
    993                 info = getPm().getApplicationInfo(ip.pkg.packageName,
    994                         PackageManager.MATCH_UNINSTALLED_PACKAGES);
    995             } catch (NameNotFoundException e) {
    996                 info = null;
    997             }
    998             if (retainData) {
    999                 assertNotNull(info);
   1000                 assertEquals(info.packageName, ip.pkg.packageName);
   1001                 File file = new File(info.dataDir);
   1002                 assertTrue(file.exists());
   1003             } else {
   1004                 assertNull(info);
   1005             }
   1006         } catch (Exception e) {
   1007             failStr(e);
   1008         } finally {
   1009             cleanUpInstall(ip);
   1010         }
   1011     }
   1012 
   1013     @LargeTest
   1014     public void testDeleteNormalInternal() throws Exception {
   1015         deleteFromRawResource(0, 0);
   1016     }
   1017 
   1018     @LargeTest
   1019     public void testDeleteSdcard() throws Exception {
   1020         // Do not run on devices with emulated external storage.
   1021         if (Environment.isExternalStorageEmulated()) {
   1022             return;
   1023         }
   1024 
   1025         deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, 0);
   1026     }
   1027 
   1028     @LargeTest
   1029     public void testDeleteNormalInternalRetainData() throws Exception {
   1030         deleteFromRawResource(0, PackageManager.DELETE_KEEP_DATA);
   1031     }
   1032 
   1033     @LargeTest
   1034     public void testDeleteSdcardRetainData() throws Exception {
   1035         // Do not run on devices with emulated external storage.
   1036         if (Environment.isExternalStorageEmulated()) {
   1037             return;
   1038         }
   1039 
   1040         deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DELETE_KEEP_DATA);
   1041     }
   1042 
   1043     void cleanUpInstall(InstallParams ip) throws Exception {
   1044         if (ip == null) {
   1045             return;
   1046         }
   1047         Runtime.getRuntime().gc();
   1048         try {
   1049             cleanUpInstall(ip.pkg.packageName);
   1050         } finally {
   1051             File outFile = new File(ip.pkg.codePath);
   1052             if (outFile != null && outFile.exists()) {
   1053                 outFile.delete();
   1054             }
   1055         }
   1056     }
   1057 
   1058     private void cleanUpInstall(String pkgName) throws Exception {
   1059         if (pkgName == null) {
   1060             return;
   1061         }
   1062         Log.i(TAG, "Deleting package : " + pkgName);
   1063         try {
   1064             final ApplicationInfo info = getPm().getApplicationInfo(pkgName,
   1065                     PackageManager.MATCH_UNINSTALLED_PACKAGES);
   1066             if (info != null) {
   1067                 final LocalIntentReceiver localReceiver = new LocalIntentReceiver();
   1068                 getPi().uninstall(pkgName,
   1069                         PackageManager.DELETE_ALL_USERS,
   1070                         localReceiver.getIntentSender());
   1071                 localReceiver.getResult();
   1072                 assertUninstalled(info);
   1073             }
   1074         } catch (IllegalArgumentException | NameNotFoundException e) {
   1075         }
   1076     }
   1077 
   1078     @LargeTest
   1079     public void testManifestInstallLocationInternal() throws Exception {
   1080         installFromRawResource("install.apk", R.raw.install_loc_internal,
   1081                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1082     }
   1083 
   1084     @LargeTest
   1085     public void testManifestInstallLocationSdcard() throws Exception {
   1086         // Do not run on devices with emulated external storage.
   1087         if (Environment.isExternalStorageEmulated()) {
   1088             return;
   1089         }
   1090 
   1091         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
   1092                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1093     }
   1094 
   1095     @LargeTest
   1096     public void testManifestInstallLocationAuto() throws Exception {
   1097         installFromRawResource("install.apk", R.raw.install_loc_auto,
   1098                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
   1099     }
   1100 
   1101     @LargeTest
   1102     public void testManifestInstallLocationUnspecified() throws Exception {
   1103         installFromRawResource("install.apk", R.raw.install_loc_unspecified,
   1104                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   1105     }
   1106 
   1107     /*
   1108      * Install a package on internal flash via PackageManager install flag. Replace
   1109      * the package via flag to install on sdcard. Make sure the new flag overrides
   1110      * the old install location.
   1111      */
   1112     @LargeTest
   1113     public void testReplaceFlagInternalSdcard() throws Exception {
   1114         // Do not run on devices with emulated external storage.
   1115         if (Environment.isExternalStorageEmulated()) {
   1116             return;
   1117         }
   1118 
   1119         int iFlags = 0;
   1120         int rFlags = PackageManager.INSTALL_EXTERNAL;
   1121         InstallParams ip = sampleInstallFromRawResource(iFlags, false);
   1122         GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
   1123         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
   1124         try {
   1125             invokeInstallPackage(ip.packageURI, replaceFlags, receiver, true);
   1126             assertInstall(ip.pkg, rFlags, ip.pkg.installLocation);
   1127         } catch (Exception e) {
   1128             failStr("Failed with exception : " + e);
   1129         } finally {
   1130             cleanUpInstall(ip);
   1131         }
   1132     }
   1133 
   1134     /*
   1135      * Install a package on sdcard via PackageManager install flag. Replace
   1136      * the package with no flags or manifest option and make sure the old
   1137      * install location is retained.
   1138      */
   1139     @LargeTest
   1140     public void testReplaceFlagSdcardInternal() throws Exception {
   1141         // Do not run on devices with emulated external storage.
   1142         if (Environment.isExternalStorageEmulated()) {
   1143             return;
   1144         }
   1145 
   1146         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1147         int rFlags = 0;
   1148         InstallParams ip = sampleInstallFromRawResource(iFlags, false);
   1149         GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
   1150         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
   1151         try {
   1152             invokeInstallPackage(ip.packageURI, replaceFlags, receiver, true);
   1153             assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);
   1154         } catch (Exception e) {
   1155             failStr("Failed with exception : " + e);
   1156         } finally {
   1157             cleanUpInstall(ip);
   1158         }
   1159     }
   1160 
   1161     @LargeTest
   1162     public void testManifestInstallLocationReplaceInternalSdcard() throws Exception {
   1163         // Do not run on devices with emulated external storage.
   1164         if (Environment.isExternalStorageEmulated()) {
   1165             return;
   1166         }
   1167 
   1168         int iFlags = 0;
   1169         int iApk = R.raw.install_loc_internal;
   1170         int rFlags = 0;
   1171         int rApk = R.raw.install_loc_sdcard;
   1172         InstallParams ip = installFromRawResource("install.apk", iApk,
   1173                 iFlags, false,
   1174                 false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1175         GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
   1176         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
   1177         try {
   1178             InstallParams rp = installFromRawResource("install.apk", rApk,
   1179                     replaceFlags, false,
   1180                     false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1181             assertInstall(rp.pkg, replaceFlags, rp.pkg.installLocation);
   1182         } catch (Exception e) {
   1183             failStr("Failed with exception : " + e);
   1184         } finally {
   1185             cleanUpInstall(ip);
   1186         }
   1187     }
   1188 
   1189     @LargeTest
   1190     public void testManifestInstallLocationReplaceSdcardInternal() throws Exception {
   1191         // Do not run on devices with emulated external storage.
   1192         if (Environment.isExternalStorageEmulated()) {
   1193             return;
   1194         }
   1195 
   1196         int iFlags = 0;
   1197         int iApk = R.raw.install_loc_sdcard;
   1198         int rFlags = 0;
   1199         int rApk = R.raw.install_loc_unspecified;
   1200         InstallParams ip = installFromRawResource("install.apk", iApk,
   1201                 iFlags, false,
   1202                 false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1203         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
   1204         try {
   1205             InstallParams rp = installFromRawResource("install.apk", rApk,
   1206                     replaceFlags, false,
   1207                     false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1208             assertInstall(rp.pkg, replaceFlags, ip.pkg.installLocation);
   1209         } catch (Exception e) {
   1210             failStr("Failed with exception : " + e);
   1211         } finally {
   1212             cleanUpInstall(ip);
   1213         }
   1214     }
   1215 
   1216     class MoveReceiver extends GenericReceiver {
   1217         String pkgName;
   1218 
   1219         final static int INVALID = -1;
   1220 
   1221         final static int REMOVED = 1;
   1222 
   1223         final static int ADDED = 2;
   1224 
   1225         int removed = INVALID;
   1226 
   1227         MoveReceiver(String pkgName) {
   1228             this.pkgName = pkgName;
   1229             filter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
   1230             filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
   1231             super.setFilter(filter);
   1232         }
   1233 
   1234         public boolean notifyNow(Intent intent) {
   1235             String action = intent.getAction();
   1236             Log.i(TAG, "MoveReceiver::" + action);
   1237             if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
   1238                 String[] list = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
   1239                 if (list != null) {
   1240                     for (String pkg : list) {
   1241                         if (pkg.equals(pkgName)) {
   1242                             removed = REMOVED;
   1243                             break;
   1244                         }
   1245                     }
   1246                 }
   1247                 removed = REMOVED;
   1248             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
   1249                 if (removed != REMOVED) {
   1250                     return false;
   1251                 }
   1252                 String[] list = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
   1253                 if (list != null) {
   1254                     for (String pkg : list) {
   1255                         if (pkg.equals(pkgName)) {
   1256                             removed = ADDED;
   1257                             return true;
   1258                         }
   1259                     }
   1260                 }
   1261             }
   1262             return false;
   1263         }
   1264     }
   1265 
   1266     public boolean invokeMovePackage(String pkgName, int flags, GenericReceiver receiver)
   1267             throws Exception {
   1268         throw new UnsupportedOperationException();
   1269     }
   1270 
   1271     private boolean invokeMovePackageFail(String pkgName, int flags, int errCode) throws Exception {
   1272         throw new UnsupportedOperationException();
   1273     }
   1274 
   1275     private int getDefaultInstallLoc() {
   1276         int origDefaultLoc = PackageInfo.INSTALL_LOCATION_AUTO;
   1277         try {
   1278             origDefaultLoc = Settings.Global.getInt(mContext.getContentResolver(),
   1279                     Settings.Global.DEFAULT_INSTALL_LOCATION);
   1280         } catch (SettingNotFoundException e1) {
   1281         }
   1282         return origDefaultLoc;
   1283     }
   1284 
   1285     private void setInstallLoc(int loc) {
   1286         Settings.Global.putInt(mContext.getContentResolver(),
   1287                 Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
   1288     }
   1289 
   1290     /*
   1291      * Tests for moving apps between internal and external storage
   1292      */
   1293     /*
   1294      * Utility function that reads a apk bundled as a raw resource
   1295      * copies it into own data directory and invokes
   1296      * PackageManager api to install first and then replace it
   1297      * again.
   1298      */
   1299 
   1300     private void moveFromRawResource(String outFileName, int rawResId, int installFlags,
   1301             int moveFlags, boolean cleanUp, boolean fail, int result) throws Exception {
   1302         int origDefaultLoc = getDefaultInstallLoc();
   1303         InstallParams ip = null;
   1304         try {
   1305             setInstallLoc(PackageHelper.APP_INSTALL_AUTO);
   1306             // Install first
   1307             ip = installFromRawResource("install.apk", rawResId, installFlags, false,
   1308                     false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   1309             ApplicationInfo oldAppInfo = getPm().getApplicationInfo(ip.pkg.packageName, 0);
   1310             if (fail) {
   1311                 assertTrue(invokeMovePackageFail(ip.pkg.packageName, moveFlags, result));
   1312                 ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
   1313                 assertNotNull(info);
   1314                 assertEquals(oldAppInfo.flags, info.flags);
   1315             } else {
   1316                 // Create receiver based on expRetCode
   1317                 MoveReceiver receiver = new MoveReceiver(ip.pkg.packageName);
   1318                 boolean retCode = invokeMovePackage(ip.pkg.packageName, moveFlags, receiver);
   1319                 assertTrue(retCode);
   1320                 ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
   1321                 assertNotNull("ApplicationInfo for recently installed application should exist",
   1322                         info);
   1323                 if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
   1324                     assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set",
   1325                             (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
   1326                     assertStartsWith("Native library dir should be in dataDir",
   1327                             info.dataDir, info.nativeLibraryDir);
   1328                 } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0) {
   1329                     assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set",
   1330                             (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
   1331                     assertStartsWith("Native library dir should point to ASEC",
   1332                             SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
   1333                 }
   1334             }
   1335         } catch (NameNotFoundException e) {
   1336             failStr("Pkg hasnt been installed correctly");
   1337         } finally {
   1338             if (ip != null) {
   1339                 cleanUpInstall(ip);
   1340             }
   1341             // Restore default install location
   1342             setInstallLoc(origDefaultLoc);
   1343         }
   1344     }
   1345 
   1346     private void sampleMoveFromRawResource(int installFlags, int moveFlags, boolean fail,
   1347             int result) throws Exception {
   1348         moveFromRawResource("install.apk",
   1349                 R.raw.install, installFlags, moveFlags, true,
   1350                 fail, result);
   1351     }
   1352 
   1353     @LargeTest
   1354     public void testMoveAppInternalToExternal() throws Exception {
   1355         // Do not run on devices with emulated external storage.
   1356         if (Environment.isExternalStorageEmulated()) {
   1357             return;
   1358         }
   1359 
   1360         int installFlags = PackageManager.INSTALL_INTERNAL;
   1361         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
   1362         boolean fail = false;
   1363         int result = PackageManager.MOVE_SUCCEEDED;
   1364         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
   1365     }
   1366 
   1367     @Suppress
   1368     @LargeTest
   1369     public void testMoveAppInternalToInternal() throws Exception {
   1370         int installFlags = PackageManager.INSTALL_INTERNAL;
   1371         int moveFlags = PackageManager.MOVE_INTERNAL;
   1372         boolean fail = true;
   1373         int result = PackageManager.MOVE_FAILED_INVALID_LOCATION;
   1374         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
   1375     }
   1376 
   1377     @LargeTest
   1378     public void testMoveAppExternalToExternal() throws Exception {
   1379         // Do not run on devices with emulated external storage.
   1380         if (Environment.isExternalStorageEmulated()) {
   1381             return;
   1382         }
   1383 
   1384         int installFlags = PackageManager.INSTALL_EXTERNAL;
   1385         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
   1386         boolean fail = true;
   1387         int result = PackageManager.MOVE_FAILED_INVALID_LOCATION;
   1388         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
   1389     }
   1390 
   1391     @LargeTest
   1392     public void testMoveAppExternalToInternal() throws Exception {
   1393         // Do not run on devices with emulated external storage.
   1394         if (Environment.isExternalStorageEmulated()) {
   1395             return;
   1396         }
   1397 
   1398         int installFlags = PackageManager.INSTALL_EXTERNAL;
   1399         int moveFlags = PackageManager.MOVE_INTERNAL;
   1400         boolean fail = false;
   1401         int result = PackageManager.MOVE_SUCCEEDED;
   1402         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
   1403     }
   1404 
   1405     @LargeTest
   1406     public void testMoveAppFailInternalToExternalDelete() throws Exception {
   1407         // Do not run on devices with emulated external storage.
   1408         if (Environment.isExternalStorageEmulated()) {
   1409             return;
   1410         }
   1411 
   1412         int installFlags = 0;
   1413         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
   1414         boolean fail = true;
   1415         final int result = PackageManager.MOVE_FAILED_DOESNT_EXIST;
   1416 
   1417         int rawResId = R.raw.install;
   1418         int origDefaultLoc = getDefaultInstallLoc();
   1419         InstallParams ip = null;
   1420         try {
   1421             PackageManager pm = getPm();
   1422             setInstallLoc(PackageHelper.APP_INSTALL_AUTO);
   1423             // Install first
   1424             ip = installFromRawResource("install.apk", R.raw.install, installFlags, false,
   1425                     false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   1426             // Delete the package now retaining data.
   1427             GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
   1428             invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
   1429             assertTrue(invokeMovePackageFail(ip.pkg.packageName, moveFlags, result));
   1430         } catch (Exception e) {
   1431             failStr(e);
   1432         } finally {
   1433             if (ip != null) {
   1434                 cleanUpInstall(ip);
   1435             }
   1436             // Restore default install location
   1437             setInstallLoc(origDefaultLoc);
   1438         }
   1439     }
   1440 
   1441     /*---------- Recommended install location tests ----*/
   1442     /*
   1443      * PrecedenceSuffixes:
   1444      * Flag : FlagI, FlagE, FlagF
   1445      * I - internal, E - external, F - forward locked, Flag suffix absent if not using any option.
   1446      * Manifest: ManifestI, ManifestE, ManifestA, Manifest suffix absent if not using any option.
   1447      * Existing: Existing suffix absent if not existing.
   1448      * User: UserI, UserE, UserA, User suffix absent if not existing.
   1449      *
   1450      */
   1451 
   1452     /*
   1453      * Install an app on internal flash
   1454      */
   1455     @LargeTest
   1456     public void testFlagI() throws Exception {
   1457         sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, true);
   1458     }
   1459 
   1460     /*
   1461      * Install an app on sdcard.
   1462      */
   1463     @LargeTest
   1464     public void testFlagE() throws Exception {
   1465         // Do not run on devices with emulated external storage.
   1466         if (Environment.isExternalStorageEmulated()) {
   1467             return;
   1468         }
   1469 
   1470         sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
   1471     }
   1472 
   1473     /*
   1474      * Install an app with both internal and manifest option set.
   1475      * should install on internal.
   1476      */
   1477     @LargeTest
   1478     public void testFlagIManifestI() throws Exception {
   1479         installFromRawResource("install.apk", R.raw.install_loc_internal,
   1480                 PackageManager.INSTALL_INTERNAL,
   1481                 true,
   1482                 false, -1,
   1483                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1484     }
   1485     /*
   1486      * Install an app with both internal and manifest preference for
   1487      * preferExternal. Should install on internal.
   1488      */
   1489     @LargeTest
   1490     public void testFlagIManifestE() throws Exception {
   1491         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
   1492                 PackageManager.INSTALL_INTERNAL,
   1493                 true,
   1494                 false, -1,
   1495                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1496     }
   1497     /*
   1498      * Install an app with both internal and manifest preference for
   1499      * auto. should install internal.
   1500      */
   1501     @LargeTest
   1502     public void testFlagIManifestA() throws Exception {
   1503         installFromRawResource("install.apk", R.raw.install_loc_auto,
   1504                 PackageManager.INSTALL_INTERNAL,
   1505                 true,
   1506                 false, -1,
   1507                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1508     }
   1509     /*
   1510      * Install an app with both external and manifest option set.
   1511      * should install externally.
   1512      */
   1513     @LargeTest
   1514     public void testFlagEManifestI() throws Exception {
   1515         // Do not run on devices with emulated external storage.
   1516         if (Environment.isExternalStorageEmulated()) {
   1517             return;
   1518         }
   1519 
   1520         installFromRawResource("install.apk", R.raw.install_loc_internal,
   1521                 PackageManager.INSTALL_EXTERNAL,
   1522                 true,
   1523                 false, -1,
   1524                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1525     }
   1526 
   1527     /*
   1528      * Install an app with both external and manifest preference for
   1529      * preferExternal. Should install externally.
   1530      */
   1531     @LargeTest
   1532     public void testFlagEManifestE() throws Exception {
   1533         // Do not run on devices with emulated external storage.
   1534         if (Environment.isExternalStorageEmulated()) {
   1535             return;
   1536         }
   1537 
   1538         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
   1539                 PackageManager.INSTALL_EXTERNAL,
   1540                 true,
   1541                 false, -1,
   1542                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1543     }
   1544 
   1545     /*
   1546      * Install an app with both external and manifest preference for
   1547      * auto. should install on external media.
   1548      */
   1549     @LargeTest
   1550     public void testFlagEManifestA() throws Exception {
   1551         // Do not run on devices with emulated external storage.
   1552         if (Environment.isExternalStorageEmulated()) {
   1553             return;
   1554         }
   1555 
   1556         installFromRawResource("install.apk", R.raw.install_loc_auto,
   1557                 PackageManager.INSTALL_EXTERNAL,
   1558                 true,
   1559                 false, -1,
   1560                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1561     }
   1562 
   1563     /*
   1564      * The following test functions verify install location for existing apps.
   1565      * ie existing app can be installed internally or externally. If install
   1566      * flag is explicitly set it should override current location. If manifest location
   1567      * is set, that should over ride current location too. if not the existing install
   1568      * location should be honoured.
   1569      * testFlagI/E/F/ExistingI/E -
   1570      */
   1571     @LargeTest
   1572     public void testFlagIExistingI() throws Exception {
   1573         int iFlags = PackageManager.INSTALL_INTERNAL;
   1574         int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
   1575         // First install.
   1576         installFromRawResource("install.apk", R.raw.install,
   1577                 iFlags,
   1578                 false,
   1579                 false, -1,
   1580                 -1);
   1581         // Replace now
   1582         installFromRawResource("install.apk", R.raw.install,
   1583                 rFlags,
   1584                 true,
   1585                 false, -1,
   1586                 -1);
   1587     }
   1588 
   1589     @LargeTest
   1590     public void testFlagIExistingE() throws Exception {
   1591         // Do not run on devices with emulated external storage.
   1592         if (Environment.isExternalStorageEmulated()) {
   1593             return;
   1594         }
   1595 
   1596         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1597         int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
   1598         // First install.
   1599         installFromRawResource("install.apk", R.raw.install,
   1600                 iFlags,
   1601                 false,
   1602                 false, -1,
   1603                 -1);
   1604         // Replace now
   1605         installFromRawResource("install.apk", R.raw.install,
   1606                 rFlags,
   1607                 true,
   1608                 false, -1,
   1609                 -1);
   1610     }
   1611 
   1612     @LargeTest
   1613     public void testFlagEExistingI() throws Exception {
   1614         // Do not run on devices with emulated external storage.
   1615         if (Environment.isExternalStorageEmulated()) {
   1616             return;
   1617         }
   1618 
   1619         int iFlags = PackageManager.INSTALL_INTERNAL;
   1620         int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
   1621         // First install.
   1622         installFromRawResource("install.apk", R.raw.install,
   1623                 iFlags,
   1624                 false,
   1625                 false, -1,
   1626                 -1);
   1627         // Replace now
   1628         installFromRawResource("install.apk", R.raw.install,
   1629                 rFlags,
   1630                 true,
   1631                 false, -1,
   1632                 -1);
   1633     }
   1634 
   1635     @LargeTest
   1636     public void testFlagEExistingE() throws Exception {
   1637         // Do not run on devices with emulated external storage.
   1638         if (Environment.isExternalStorageEmulated()) {
   1639             return;
   1640         }
   1641 
   1642         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1643         int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
   1644         // First install.
   1645         installFromRawResource("install.apk", R.raw.install,
   1646                 iFlags,
   1647                 false,
   1648                 false, -1,
   1649                 -1);
   1650         // Replace now
   1651         installFromRawResource("install.apk", R.raw.install,
   1652                 rFlags,
   1653                 true,
   1654                 false, -1,
   1655                 -1);
   1656     }
   1657 
   1658     /*
   1659      * The following set of tests verify the installation of apps with
   1660      * install location attribute set to internalOnly, preferExternal and auto.
   1661      * The manifest option should dictate the install location.
   1662      * public void testManifestI/E/A
   1663      * TODO out of memory fall back behaviour.
   1664      */
   1665     @LargeTest
   1666     public void testManifestI() throws Exception {
   1667         installFromRawResource("install.apk", R.raw.install_loc_internal,
   1668                 0,
   1669                 true,
   1670                 false, -1,
   1671                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1672     }
   1673 
   1674     @LargeTest
   1675     public void testManifestE() throws Exception {
   1676         // Do not run on devices with emulated external storage.
   1677         if (Environment.isExternalStorageEmulated()) {
   1678             return;
   1679         }
   1680 
   1681         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
   1682                 0,
   1683                 true,
   1684                 false, -1,
   1685                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1686     }
   1687 
   1688     @LargeTest
   1689     public void testManifestA() throws Exception {
   1690         installFromRawResource("install.apk", R.raw.install_loc_auto,
   1691                 0,
   1692                 true,
   1693                 false, -1,
   1694                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1695     }
   1696 
   1697     /*
   1698      * The following set of tests verify the installation of apps
   1699      * with install location attribute set to internalOnly, preferExternal and auto
   1700      * for already existing apps. The manifest option should take precedence.
   1701      * TODO add out of memory fall back behaviour.
   1702      * testManifestI/E/AExistingI/E
   1703      */
   1704     @LargeTest
   1705     public void testManifestIExistingI() throws Exception {
   1706         int iFlags = PackageManager.INSTALL_INTERNAL;
   1707         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1708         // First install.
   1709         installFromRawResource("install.apk", R.raw.install,
   1710                 iFlags,
   1711                 false,
   1712                 false, -1,
   1713                 -1);
   1714         // Replace now
   1715         installFromRawResource("install.apk", R.raw.install_loc_internal,
   1716                 rFlags,
   1717                 true,
   1718                 false, -1,
   1719                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1720     }
   1721 
   1722     @LargeTest
   1723     public void testManifestIExistingE() throws Exception {
   1724         // Do not run on devices with emulated external storage.
   1725         if (Environment.isExternalStorageEmulated()) {
   1726             return;
   1727         }
   1728 
   1729         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1730         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1731         // First install.
   1732         installFromRawResource("install.apk", R.raw.install,
   1733                 iFlags,
   1734                 false,
   1735                 false, -1,
   1736                 -1);
   1737         // Replace now
   1738         installFromRawResource("install.apk", R.raw.install_loc_internal,
   1739                 rFlags,
   1740                 true,
   1741                 false, -1,
   1742                 PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1743     }
   1744 
   1745     @LargeTest
   1746     public void testManifestEExistingI() throws Exception {
   1747         // Do not run on devices with emulated external storage.
   1748         if (Environment.isExternalStorageEmulated()) {
   1749             return;
   1750         }
   1751 
   1752         int iFlags = PackageManager.INSTALL_INTERNAL;
   1753         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1754         // First install.
   1755         installFromRawResource("install.apk", R.raw.install,
   1756                 iFlags,
   1757                 false,
   1758                 false, -1,
   1759                 -1);
   1760         // Replace now
   1761         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
   1762                 rFlags,
   1763                 true,
   1764                 false, -1,
   1765                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1766     }
   1767 
   1768     @LargeTest
   1769     public void testManifestEExistingE() throws Exception {
   1770         // Do not run on devices with emulated external storage.
   1771         if (Environment.isExternalStorageEmulated()) {
   1772             return;
   1773         }
   1774 
   1775         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1776         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1777         // First install.
   1778         installFromRawResource("install.apk", R.raw.install,
   1779                 iFlags,
   1780                 false,
   1781                 false, -1,
   1782                 -1);
   1783         // Replace now
   1784         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
   1785                 rFlags,
   1786                 true,
   1787                 false, -1,
   1788                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1789     }
   1790 
   1791     @LargeTest
   1792     public void testManifestAExistingI() throws Exception {
   1793         int iFlags = PackageManager.INSTALL_INTERNAL;
   1794         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1795         // First install.
   1796         installFromRawResource("install.apk", R.raw.install,
   1797                 iFlags,
   1798                 false,
   1799                 false, -1,
   1800                 -1);
   1801         // Replace now
   1802         installFromRawResource("install.apk", R.raw.install_loc_auto,
   1803                 rFlags,
   1804                 true,
   1805                 false, -1,
   1806                 PackageInfo.INSTALL_LOCATION_AUTO);
   1807     }
   1808 
   1809     @LargeTest
   1810     public void testManifestAExistingE() throws Exception {
   1811         // Do not run on devices with emulated external storage.
   1812         if (Environment.isExternalStorageEmulated()) {
   1813             return;
   1814         }
   1815 
   1816         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1817         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1818         // First install.
   1819         installFromRawResource("install.apk", R.raw.install,
   1820                 iFlags,
   1821                 false,
   1822                 false, -1,
   1823                 -1);
   1824         // Replace now
   1825         installFromRawResource("install.apk", R.raw.install_loc_auto,
   1826                 rFlags,
   1827                 true,
   1828                 false, -1,
   1829                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1830     }
   1831 
   1832     /*
   1833      * The following set of tests check install location for existing
   1834      * application based on user setting.
   1835      */
   1836     private int getExpectedInstallLocation(int userSetting) {
   1837         int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
   1838         boolean enable = getUserSettingSetInstallLocation();
   1839         if (enable) {
   1840             if (userSetting == PackageHelper.APP_INSTALL_AUTO) {
   1841                 iloc = PackageInfo.INSTALL_LOCATION_AUTO;
   1842             } else if (userSetting == PackageHelper.APP_INSTALL_EXTERNAL) {
   1843                 iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
   1844             } else if (userSetting == PackageHelper.APP_INSTALL_INTERNAL) {
   1845                 iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
   1846             }
   1847         }
   1848         return iloc;
   1849     }
   1850 
   1851     private void setExistingXUserX(int userSetting, int iFlags, int iloc) throws Exception {
   1852         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   1853         // First install.
   1854         installFromRawResource("install.apk", R.raw.install,
   1855                 iFlags,
   1856                 false,
   1857                 false, -1,
   1858                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   1859         int origSetting = getDefaultInstallLoc();
   1860         try {
   1861             // Set user setting
   1862             setInstallLoc(userSetting);
   1863             // Replace now
   1864             installFromRawResource("install.apk", R.raw.install,
   1865                     rFlags,
   1866                     true,
   1867                     false, -1,
   1868                     iloc);
   1869         } finally {
   1870             setInstallLoc(origSetting);
   1871         }
   1872     }
   1873     @LargeTest
   1874     public void testExistingIUserI() throws Exception {
   1875         int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
   1876         int iFlags = PackageManager.INSTALL_INTERNAL;
   1877         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1878     }
   1879 
   1880     @LargeTest
   1881     public void testExistingIUserE() throws Exception {
   1882         // Do not run on devices with emulated external storage.
   1883         if (Environment.isExternalStorageEmulated()) {
   1884             return;
   1885         }
   1886 
   1887         int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
   1888         int iFlags = PackageManager.INSTALL_INTERNAL;
   1889         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1890     }
   1891 
   1892     @LargeTest
   1893     public void testExistingIUserA() throws Exception {
   1894         int userSetting = PackageHelper.APP_INSTALL_AUTO;
   1895         int iFlags = PackageManager.INSTALL_INTERNAL;
   1896         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   1897     }
   1898 
   1899     @LargeTest
   1900     public void testExistingEUserI() throws Exception {
   1901         // Do not run on devices with emulated external storage.
   1902         if (Environment.isExternalStorageEmulated()) {
   1903             return;
   1904         }
   1905 
   1906         int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
   1907         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1908         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1909     }
   1910 
   1911     @LargeTest
   1912     public void testExistingEUserE() throws Exception {
   1913         // Do not run on devices with emulated external storage.
   1914         if (Environment.isExternalStorageEmulated()) {
   1915             return;
   1916         }
   1917 
   1918         int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
   1919         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1920         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1921     }
   1922 
   1923     @LargeTest
   1924     public void testExistingEUserA() throws Exception {
   1925         // Do not run on devices with emulated external storage.
   1926         if (Environment.isExternalStorageEmulated()) {
   1927             return;
   1928         }
   1929 
   1930         int userSetting = PackageHelper.APP_INSTALL_AUTO;
   1931         int iFlags = PackageManager.INSTALL_EXTERNAL;
   1932         setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
   1933     }
   1934 
   1935     /*
   1936      * The following set of tests verify that the user setting defines
   1937      * the install location.
   1938      *
   1939      */
   1940     private boolean getUserSettingSetInstallLocation() {
   1941         try {
   1942             return Settings.Global.getInt(
   1943                     mContext.getContentResolver(), Settings.Global.SET_INSTALL_LOCATION) != 0;
   1944         } catch (SettingNotFoundException e1) {
   1945         }
   1946         return false;
   1947     }
   1948 
   1949     private void setUserSettingSetInstallLocation(boolean value) {
   1950         Settings.Global.putInt(mContext.getContentResolver(),
   1951                 Settings.Global.SET_INSTALL_LOCATION, value ? 1 : 0);
   1952     }
   1953 
   1954     private void setUserX(boolean enable, int userSetting, int iloc) throws Exception {
   1955         boolean origUserSetting = getUserSettingSetInstallLocation();
   1956         int origSetting = getDefaultInstallLoc();
   1957         try {
   1958             setUserSettingSetInstallLocation(enable);
   1959             // Set user setting
   1960             setInstallLoc(userSetting);
   1961             // Replace now
   1962             installFromRawResource("install.apk", R.raw.install,
   1963                     0,
   1964                     true,
   1965                     false, -1,
   1966                     iloc);
   1967         } finally {
   1968             // Restore original setting
   1969             setUserSettingSetInstallLocation(origUserSetting);
   1970             setInstallLoc(origSetting);
   1971         }
   1972     }
   1973     @LargeTest
   1974     public void testUserI() throws Exception {
   1975         int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
   1976         int iloc = getExpectedInstallLocation(userSetting);
   1977         setUserX(true, userSetting, iloc);
   1978     }
   1979 
   1980     @LargeTest
   1981     public void testUserE() throws Exception {
   1982         // Do not run on devices with emulated external storage.
   1983         if (Environment.isExternalStorageEmulated()) {
   1984             return;
   1985         }
   1986 
   1987         int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
   1988         int iloc = getExpectedInstallLocation(userSetting);
   1989         setUserX(true, userSetting, iloc);
   1990     }
   1991 
   1992     @LargeTest
   1993     public void testUserA() throws Exception {
   1994         int userSetting = PackageHelper.APP_INSTALL_AUTO;
   1995         int iloc = getExpectedInstallLocation(userSetting);
   1996         setUserX(true, userSetting, iloc);
   1997     }
   1998 
   1999     /*
   2000      * The following set of tests turn on/off the basic
   2001      * user setting for turning on install location.
   2002      */
   2003     @LargeTest
   2004     public void testUserPrefOffUserI() throws Exception {
   2005         int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
   2006         int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
   2007         setUserX(false, userSetting, iloc);
   2008     }
   2009 
   2010     @LargeTest
   2011     public void testUserPrefOffUserE() throws Exception {
   2012         // Do not run on devices with emulated external storage.
   2013         if (Environment.isExternalStorageEmulated()) {
   2014             return;
   2015         }
   2016 
   2017         int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
   2018         int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
   2019         setUserX(false, userSetting, iloc);
   2020     }
   2021 
   2022     @LargeTest
   2023     public void testUserPrefOffA() throws Exception {
   2024         int userSetting = PackageHelper.APP_INSTALL_AUTO;
   2025         int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
   2026         setUserX(false, userSetting, iloc);
   2027     }
   2028 
   2029     static final String BASE_PERMISSIONS_DEFINED[] = new String[] {
   2030         PERM_PACKAGE, "com.android.unit_tests.install_decl_perm",
   2031         PERM_DEFINED,
   2032         "com.android.frameworks.coretests.NORMAL",
   2033         "com.android.frameworks.coretests.DANGEROUS",
   2034         "com.android.frameworks.coretests.SIGNATURE",
   2035     };
   2036 
   2037     static final String BASE_PERMISSIONS_UNDEFINED[] = new String[] {
   2038         PERM_PACKAGE, "com.android.frameworks.coretests.install_decl_perm",
   2039         PERM_UNDEFINED,
   2040         "com.android.frameworks.coretests.NORMAL",
   2041         "com.android.frameworks.coretests.DANGEROUS",
   2042         "com.android.frameworks.coretests.SIGNATURE",
   2043     };
   2044 
   2045     static final String BASE_PERMISSIONS_USED[] = new String[] {
   2046         PERM_PACKAGE, "com.android.frameworks.coretests.install_use_perm_good",
   2047         PERM_USED,
   2048         "com.android.frameworks.coretests.NORMAL",
   2049         "com.android.frameworks.coretests.DANGEROUS",
   2050         "com.android.frameworks.coretests.SIGNATURE",
   2051     };
   2052 
   2053     static final String BASE_PERMISSIONS_NOTUSED[] = new String[] {
   2054         PERM_PACKAGE, "com.android.frameworks.coretests.install_use_perm_good",
   2055         PERM_NOTUSED,
   2056         "com.android.frameworks.coretests.NORMAL",
   2057         "com.android.frameworks.coretests.DANGEROUS",
   2058         "com.android.frameworks.coretests.SIGNATURE",
   2059     };
   2060 
   2061     static final String BASE_PERMISSIONS_SIGUSED[] = new String[] {
   2062         PERM_PACKAGE, "com.android.frameworks.coretests.install_use_perm_good",
   2063         PERM_USED,
   2064         "com.android.frameworks.coretests.SIGNATURE",
   2065         PERM_NOTUSED,
   2066         "com.android.frameworks.coretests.NORMAL",
   2067         "com.android.frameworks.coretests.DANGEROUS",
   2068     };
   2069 
   2070     /*
   2071      * Ensure that permissions are properly declared.
   2072      */
   2073     @LargeTest
   2074     public void testInstallDeclaresPermissions() throws Exception {
   2075         InstallParams ip = null;
   2076         InstallParams ip2 = null;
   2077         try {
   2078             // **: Upon installing a package, are its declared permissions published?
   2079 
   2080             int iFlags = PackageManager.INSTALL_INTERNAL;
   2081             int iApk = R.raw.install_decl_perm;
   2082             ip = installFromRawResource("install.apk", iApk,
   2083                     iFlags, false,
   2084                     false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   2085             assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);
   2086             assertPermissions(BASE_PERMISSIONS_DEFINED);
   2087 
   2088             // **: Upon installing package, are its permissions granted?
   2089 
   2090             int i2Flags = PackageManager.INSTALL_INTERNAL;
   2091             int i2Apk = R.raw.install_use_perm_good;
   2092             ip2 = installFromRawResource("install2.apk", i2Apk,
   2093                     i2Flags, false,
   2094                     false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   2095             assertInstall(ip2.pkg, i2Flags, ip2.pkg.installLocation);
   2096             assertPermissions(BASE_PERMISSIONS_USED);
   2097 
   2098             // **: Upon removing but not deleting, are permissions retained?
   2099 
   2100             GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
   2101 
   2102             try {
   2103                 invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
   2104             } catch (Exception e) {
   2105                 failStr(e);
   2106             }
   2107             assertPermissions(BASE_PERMISSIONS_DEFINED);
   2108             assertPermissions(BASE_PERMISSIONS_USED);
   2109 
   2110             // **: Upon re-installing, are permissions retained?
   2111 
   2112             ip = installFromRawResource("install.apk", iApk,
   2113                     iFlags | PackageManager.INSTALL_REPLACE_EXISTING, false,
   2114                     false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   2115             assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);
   2116             assertPermissions(BASE_PERMISSIONS_DEFINED);
   2117             assertPermissions(BASE_PERMISSIONS_USED);
   2118 
   2119             // **: Upon deleting package, are all permissions removed?
   2120 
   2121             try {
   2122                 invokeDeletePackage(ip.pkg.packageName, 0, receiver);
   2123                 ip = null;
   2124             } catch (Exception e) {
   2125                 failStr(e);
   2126             }
   2127             assertPermissions(BASE_PERMISSIONS_UNDEFINED);
   2128             assertPermissions(BASE_PERMISSIONS_NOTUSED);
   2129 
   2130             // **: Delete package using permissions; nothing to check here.
   2131 
   2132             GenericReceiver receiver2 = new DeleteReceiver(ip2.pkg.packageName);
   2133             try {
   2134                 invokeDeletePackage(ip2.pkg.packageName, 0, receiver);
   2135                 ip2 = null;
   2136             } catch (Exception e) {
   2137                 failStr(e);
   2138             }
   2139 
   2140             // **: Re-install package using permissions; no permissions can be granted.
   2141 
   2142             ip2 = installFromRawResource("install2.apk", i2Apk,
   2143                     i2Flags, false,
   2144                     false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   2145             assertInstall(ip2.pkg, i2Flags, ip2.pkg.installLocation);
   2146             assertPermissions(BASE_PERMISSIONS_NOTUSED);
   2147 
   2148             // **: Upon installing declaring package, are sig permissions granted
   2149             // to other apps (but not other perms)?
   2150 
   2151             ip = installFromRawResource("install.apk", iApk,
   2152                     iFlags, false,
   2153                     false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   2154             assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);
   2155             assertPermissions(BASE_PERMISSIONS_DEFINED);
   2156             assertPermissions(BASE_PERMISSIONS_SIGUSED);
   2157 
   2158             // **: Re-install package using permissions; are all permissions granted?
   2159 
   2160             ip2 = installFromRawResource("install2.apk", i2Apk,
   2161                     i2Flags | PackageManager.INSTALL_REPLACE_EXISTING, false,
   2162                     false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   2163             assertInstall(ip2.pkg, i2Flags, ip2.pkg.installLocation);
   2164             assertPermissions(BASE_PERMISSIONS_NOTUSED);
   2165 
   2166             // **: Upon deleting package, are all permissions removed?
   2167 
   2168             try {
   2169                 invokeDeletePackage(ip.pkg.packageName, 0, receiver);
   2170                 ip = null;
   2171             } catch (Exception e) {
   2172                 failStr(e);
   2173             }
   2174             assertPermissions(BASE_PERMISSIONS_UNDEFINED);
   2175             assertPermissions(BASE_PERMISSIONS_NOTUSED);
   2176 
   2177             // **: Delete package using permissions; nothing to check here.
   2178 
   2179             try {
   2180                 invokeDeletePackage(ip2.pkg.packageName, 0, receiver);
   2181                 ip2 = null;
   2182             } catch (Exception e) {
   2183                 failStr(e);
   2184             }
   2185 
   2186         } finally {
   2187             if (ip2 != null) {
   2188                 cleanUpInstall(ip2);
   2189             }
   2190             if (ip != null) {
   2191                 cleanUpInstall(ip);
   2192             }
   2193         }
   2194     }
   2195 
   2196     /*
   2197      * The following series of tests are related to upgrading apps with
   2198      * different certificates.
   2199      */
   2200     private int APP1_UNSIGNED = R.raw.install_app1_unsigned;
   2201 
   2202     private int APP1_CERT1 = R.raw.install_app1_cert1;
   2203 
   2204     private int APP1_CERT2 = R.raw.install_app1_cert2;
   2205 
   2206     private int APP1_CERT1_CERT2 = R.raw.install_app1_cert1_cert2;
   2207 
   2208     private int APP1_CERT3_CERT4 = R.raw.install_app1_cert3_cert4;
   2209 
   2210     private int APP1_CERT3 = R.raw.install_app1_cert3;
   2211 
   2212     private int APP2_UNSIGNED = R.raw.install_app2_unsigned;
   2213 
   2214     private int APP2_CERT1 = R.raw.install_app2_cert1;
   2215 
   2216     private int APP2_CERT2 = R.raw.install_app2_cert2;
   2217 
   2218     private int APP2_CERT1_CERT2 = R.raw.install_app2_cert1_cert2;
   2219 
   2220     private int APP2_CERT3 = R.raw.install_app2_cert3;
   2221 
   2222     private InstallParams replaceCerts(int apk1, int apk2, boolean cleanUp, boolean fail,
   2223             int retCode) throws Exception {
   2224         int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   2225         String apk1Name = "install1.apk";
   2226         String apk2Name = "install2.apk";
   2227         PackageParser.Package pkg1 = getParsedPackage(apk1Name, apk1);
   2228         try {
   2229             InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
   2230                     false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2231             installFromRawResource(apk2Name, apk2, rFlags, false,
   2232                     fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2233             return ip;
   2234         } catch (Exception e) {
   2235             failStr(e.getMessage());
   2236         } finally {
   2237             if (cleanUp) {
   2238                 cleanUpInstall(pkg1.packageName);
   2239             }
   2240         }
   2241         return null;
   2242     }
   2243 
   2244     /*
   2245      * Test that an app signed with two certificates can be upgraded by the
   2246      * same app signed with two certificates.
   2247      */
   2248     @LargeTest
   2249     public void testReplaceMatchAllCerts() throws Exception {
   2250         replaceCerts(APP1_CERT1_CERT2, APP1_CERT1_CERT2, true, false, -1);
   2251     }
   2252 
   2253     /*
   2254      * Test that an app signed with two certificates cannot be upgraded
   2255      * by an app signed with a different certificate.
   2256      */
   2257     @LargeTest
   2258     public void testReplaceMatchNoCerts1() throws Exception {
   2259         replaceCerts(APP1_CERT1_CERT2, APP1_CERT3, true, true,
   2260                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2261     }
   2262 
   2263     /*
   2264      * Test that an app signed with two certificates cannot be upgraded
   2265      * by an app signed with a different certificate.
   2266      */
   2267     @LargeTest
   2268     public void testReplaceMatchNoCerts2() throws Exception {
   2269         replaceCerts(APP1_CERT1_CERT2, APP1_CERT3_CERT4, true, true,
   2270                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2271     }
   2272 
   2273     /*
   2274      * Test that an app signed with two certificates cannot be upgraded by
   2275      * an app signed with a subset of initial certificates.
   2276      */
   2277     @LargeTest
   2278     public void testReplaceMatchSomeCerts1() throws Exception {
   2279         replaceCerts(APP1_CERT1_CERT2, APP1_CERT1, true, true,
   2280                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2281     }
   2282 
   2283     /*
   2284      * Test that an app signed with two certificates cannot be upgraded by
   2285      * an app signed with the last certificate.
   2286      */
   2287     @LargeTest
   2288     public void testReplaceMatchSomeCerts2() throws Exception {
   2289         replaceCerts(APP1_CERT1_CERT2, APP1_CERT2, true, true,
   2290                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2291     }
   2292 
   2293     /*
   2294      * Test that an app signed with a certificate can be upgraded by app
   2295      * signed with a superset of certificates.
   2296      */
   2297     @LargeTest
   2298     public void testReplaceMatchMoreCerts() throws Exception {
   2299         replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, true, true,
   2300                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2301     }
   2302 
   2303     /*
   2304      * Test that an app signed with a certificate can be upgraded by app
   2305      * signed with a superset of certificates. Then verify that the an app
   2306      * signed with the original set of certs cannot upgrade the new one.
   2307      */
   2308     @LargeTest
   2309     public void testReplaceMatchMoreCertsReplaceSomeCerts() throws Exception {
   2310         InstallParams ip = replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, false, true,
   2311                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2312         try {
   2313             int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
   2314             installFromRawResource("install.apk", APP1_CERT1, rFlags, false,
   2315                     false, -1,
   2316                     PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2317         } catch (Exception e) {
   2318             failStr(e.getMessage());
   2319         } finally {
   2320             if (ip != null) {
   2321                 cleanUpInstall(ip);
   2322             }
   2323         }
   2324     }
   2325 
   2326     /**
   2327      * The following tests are related to testing KeySets-based key rotation
   2328      */
   2329     /*
   2330      * Check if an apk which does not specify an upgrade-keyset may be upgraded
   2331      * by an apk which does
   2332      */
   2333     public void testNoKSToUpgradeKS() throws Exception {
   2334         replaceCerts(R.raw.keyset_sa_unone, R.raw.keyset_sa_ua, true, false, -1);
   2335     }
   2336 
   2337     /*
   2338      * Check if an apk which does specify an upgrade-keyset may be downgraded to
   2339      * an apk which does not
   2340      */
   2341     public void testUpgradeKSToNoKS() throws Exception {
   2342         replaceCerts(R.raw.keyset_sa_ua, R.raw.keyset_sa_unone, true, false, -1);
   2343     }
   2344 
   2345     /*
   2346      * Check if an apk signed by a key other than the upgrade keyset can update
   2347      * an app
   2348      */
   2349     public void testUpgradeKSWithWrongKey() throws Exception {
   2350         replaceCerts(R.raw.keyset_sa_ua, R.raw.keyset_sb_ua, true, true,
   2351                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2352     }
   2353 
   2354     /*
   2355      * Check if an apk signed by its signing key, which is not an upgrade key,
   2356      * can upgrade an app.
   2357      */
   2358     public void testUpgradeKSWithWrongSigningKey() throws Exception {
   2359         replaceCerts(R.raw.keyset_sa_ub, R.raw.keyset_sa_ub, true, true,
   2360                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2361     }
   2362 
   2363     /*
   2364      * Check if an apk signed by its upgrade key, which is not its signing key,
   2365      * can upgrade an app.
   2366      */
   2367     public void testUpgradeKSWithUpgradeKey() throws Exception {
   2368         replaceCerts(R.raw.keyset_sa_ub, R.raw.keyset_sb_ub, true, false, -1);
   2369     }
   2370     /*
   2371      * Check if an apk signed by its upgrade key, which is its signing key, can
   2372      * upgrade an app.
   2373      */
   2374     public void testUpgradeKSWithSigningUpgradeKey() throws Exception {
   2375         replaceCerts(R.raw.keyset_sa_ua, R.raw.keyset_sa_ua, true, false, -1);
   2376     }
   2377 
   2378     /*
   2379      * Check if an apk signed by multiple keys, one of which is its upgrade key,
   2380      * can upgrade an app.
   2381      */
   2382     public void testMultipleUpgradeKSWithUpgradeKey() throws Exception {
   2383         replaceCerts(R.raw.keyset_sa_ua, R.raw.keyset_sab_ua, true, false, -1);
   2384     }
   2385 
   2386     /*
   2387      * Check if an apk signed by multiple keys, one of which is its signing key,
   2388      * but none of which is an upgrade key, can upgrade an app.
   2389      */
   2390     public void testMultipleUpgradeKSWithSigningKey() throws Exception {
   2391         replaceCerts(R.raw.keyset_sau_ub, R.raw.keyset_sa_ua, true, true,
   2392                 PackageInstaller.STATUS_FAILURE_CONFLICT);
   2393     }
   2394 
   2395     /*
   2396      * Check if an apk which defines multiple (two) upgrade keysets is
   2397      * upgrade-able by either.
   2398      */
   2399     public void testUpgradeKSWithMultipleUpgradeKeySets() throws Exception {
   2400         replaceCerts(R.raw.keyset_sa_ua_ub, R.raw.keyset_sa_ua, true, false, -1);
   2401         replaceCerts(R.raw.keyset_sa_ua_ub, R.raw.keyset_sb_ub, true, false, -1);
   2402     }
   2403 
   2404     /*
   2405      * Check if an apk's sigs are changed after upgrading with a non-signing
   2406      * key.
   2407      *
   2408      * TODO: consider checking against hard-coded Signatures in the Sig-tests
   2409      */
   2410     public void testSigChangeAfterUpgrade() throws Exception {
   2411         // install original apk and grab sigs
   2412         installFromRawResource("tmp.apk", R.raw.keyset_sa_ub,
   2413                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2414         PackageManager pm = getPm();
   2415         String pkgName = "com.android.frameworks.coretests.keysets";
   2416         PackageInfo pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2417         assertTrue("Package should only have one signature, sig A",
   2418                 pi.signatures.length == 1);
   2419         String sigBefore = pi.signatures[0].toCharsString();
   2420         // install apk signed by different upgrade KeySet
   2421         installFromRawResource("tmp2.apk", R.raw.keyset_sb_ub,
   2422                 PackageManager.INSTALL_REPLACE_EXISTING, false, false, -1,
   2423                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2424         pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2425         assertTrue("Package should only have one signature, sig B",
   2426                 pi.signatures.length == 1);
   2427         String sigAfter = pi.signatures[0].toCharsString();
   2428         assertFalse("Package signatures did not change after upgrade!",
   2429                 sigBefore.equals(sigAfter));
   2430         cleanUpInstall(pkgName);
   2431     }
   2432 
   2433     /*
   2434      * Check if an apk's sig is the same  after upgrading with a signing
   2435      * key.
   2436      */
   2437     public void testSigSameAfterUpgrade() throws Exception {
   2438         // install original apk and grab sigs
   2439         installFromRawResource("tmp.apk", R.raw.keyset_sa_ua,
   2440                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2441         PackageManager pm = getPm();
   2442         String pkgName = "com.android.frameworks.coretests.keysets";
   2443         PackageInfo pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2444         assertTrue("Package should only have one signature, sig A",
   2445                 pi.signatures.length == 1);
   2446         String sigBefore = pi.signatures[0].toCharsString();
   2447         // install apk signed by same upgrade KeySet
   2448         installFromRawResource("tmp2.apk", R.raw.keyset_sa_ua,
   2449                 PackageManager.INSTALL_REPLACE_EXISTING, false, false, -1,
   2450                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2451         pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2452         assertTrue("Package should only have one signature, sig A",
   2453                 pi.signatures.length == 1);
   2454         String sigAfter = pi.signatures[0].toCharsString();
   2455         assertTrue("Package signatures changed after upgrade!",
   2456                 sigBefore.equals(sigAfter));
   2457         cleanUpInstall(pkgName);
   2458     }
   2459 
   2460     /*
   2461      * Check if an apk's sigs are the same after upgrading with an app with
   2462      * a subset of the original signing keys.
   2463      */
   2464     public void testSigRemovedAfterUpgrade() throws Exception {
   2465         // install original apk and grab sigs
   2466         installFromRawResource("tmp.apk", R.raw.keyset_sab_ua,
   2467                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2468         PackageManager pm = getPm();
   2469         String pkgName = "com.android.frameworks.coretests.keysets";
   2470         PackageInfo pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2471         assertTrue("Package should have two signatures, sig A and sig B",
   2472                 pi.signatures.length == 2);
   2473         Set<String> sigsBefore = new HashSet<String>();
   2474         for (int i = 0; i < pi.signatures.length; i++) {
   2475             sigsBefore.add(pi.signatures[i].toCharsString());
   2476         }
   2477         // install apk signed subset upgrade KeySet
   2478         installFromRawResource("tmp2.apk", R.raw.keyset_sa_ua,
   2479                 PackageManager.INSTALL_REPLACE_EXISTING, false, false, -1,
   2480                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2481         pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2482         assertTrue("Package should only have one signature, sig A",
   2483                 pi.signatures.length == 1);
   2484         String sigAfter = pi.signatures[0].toCharsString();
   2485         assertTrue("Original package signatures did not contain new sig",
   2486                 sigsBefore.contains(sigAfter));
   2487         cleanUpInstall(pkgName);
   2488     }
   2489 
   2490     /*
   2491      * Check if an apk's sigs are added to after upgrading with an app with
   2492      * a superset of the original signing keys.
   2493      */
   2494     public void testSigAddedAfterUpgrade() throws Exception {
   2495         // install original apk and grab sigs
   2496         installFromRawResource("tmp.apk", R.raw.keyset_sa_ua,
   2497                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2498         PackageManager pm = getPm();
   2499         String pkgName = "com.android.frameworks.coretests.keysets";
   2500         PackageInfo pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2501         assertTrue("Package should only have one signature, sig A",
   2502                 pi.signatures.length == 1);
   2503         String sigBefore = pi.signatures[0].toCharsString();
   2504         // install apk signed subset upgrade KeySet
   2505         installFromRawResource("tmp2.apk", R.raw.keyset_sab_ua,
   2506                 PackageManager.INSTALL_REPLACE_EXISTING, false, false, -1,
   2507                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2508         pi = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
   2509         assertTrue("Package should have two signatures, sig A and sig B",
   2510                 pi.signatures.length == 2);
   2511         Set<String> sigsAfter = new HashSet<String>();
   2512         for (int i = 0; i < pi.signatures.length; i++) {
   2513             sigsAfter.add(pi.signatures[i].toCharsString());
   2514         }
   2515         assertTrue("Package signatures did not change after upgrade!",
   2516                 sigsAfter.contains(sigBefore));
   2517         cleanUpInstall(pkgName);
   2518     }
   2519 
   2520     /*
   2521      * Check if an apk gains signature-level permission after changing to the a
   2522      * new signature, for which a permission should be granted.
   2523      */
   2524     public void testUpgradeSigPermGained() throws Exception {
   2525         // install apk which defines permission
   2526         installFromRawResource("permDef.apk", R.raw.keyset_permdef_sa_unone,
   2527                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2528         // install apk which uses permission but does not have sig
   2529         installFromRawResource("permUse.apk", R.raw.keyset_permuse_sb_ua_ub,
   2530                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2531         // verify that package does not have perm before
   2532         PackageManager pm = getPm();
   2533         String permPkgName = "com.android.frameworks.coretests.keysets_permdef";
   2534         String pkgName = "com.android.frameworks.coretests.keysets";
   2535         String permName = "com.android.frameworks.coretests.keysets_permdef.keyset_perm";
   2536         assertFalse("keyset permission granted to app without same signature!",
   2537                     pm.checkPermission(permName, pkgName)
   2538                     == PackageManager.PERMISSION_GRANTED);
   2539         // upgrade to apk with perm signature
   2540         installFromRawResource("permUse2.apk", R.raw.keyset_permuse_sa_ua_ub,
   2541                 PackageManager.INSTALL_REPLACE_EXISTING, false, false, -1,
   2542                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2543         assertTrue("keyset permission not granted to app after upgrade to same sig",
   2544                     pm.checkPermission(permName, pkgName)
   2545                     == PackageManager.PERMISSION_GRANTED);
   2546         cleanUpInstall(permPkgName);
   2547         cleanUpInstall(pkgName);
   2548     }
   2549 
   2550     /*
   2551      * Check if an apk loses signature-level permission after changing to the a
   2552      * new signature, from one which a permission should be granted.
   2553      */
   2554     public void testUpgradeSigPermLost() throws Exception {
   2555         // install apk which defines permission
   2556         installFromRawResource("permDef.apk", R.raw.keyset_permdef_sa_unone,
   2557                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2558         // install apk which uses permission, signed by same sig
   2559         installFromRawResource("permUse.apk", R.raw.keyset_permuse_sa_ua_ub,
   2560                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2561         // verify that package does not have perm before
   2562         PackageManager pm = getPm();
   2563         String permPkgName = "com.android.frameworks.coretests.keysets_permdef";
   2564         String pkgName = "com.android.frameworks.coretests.keysets";
   2565         String permName = "com.android.frameworks.coretests.keysets_permdef.keyset_perm";
   2566         assertTrue("keyset permission not granted to app with same sig",
   2567                     pm.checkPermission(permName, pkgName)
   2568                     == PackageManager.PERMISSION_GRANTED);
   2569         // upgrade to apk without perm signature
   2570         installFromRawResource("permUse2.apk", R.raw.keyset_permuse_sb_ua_ub,
   2571                 PackageManager.INSTALL_REPLACE_EXISTING, false, false, -1,
   2572                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2573 
   2574         assertFalse("keyset permission not revoked from app which upgraded to a "
   2575                     + "different signature",
   2576                     pm.checkPermission(permName, pkgName)
   2577                     == PackageManager.PERMISSION_GRANTED);
   2578         cleanUpInstall(permPkgName);
   2579         cleanUpInstall(pkgName);
   2580     }
   2581 
   2582     /**
   2583      * The following tests are related to testing KeySets-based API
   2584      */
   2585 
   2586     /*
   2587      * testGetSigningKeySetNull - ensure getSigningKeySet() returns null on null
   2588      * input and when calling a package other than that which made the call.
   2589      */
   2590     public void testGetSigningKeySet() throws Exception {
   2591         PackageManager pm = getPm();
   2592         String mPkgName = mContext.getPackageName();
   2593         String otherPkgName = "com.android.frameworks.coretests.keysets_api";
   2594         KeySet ks;
   2595         try {
   2596             ks = pm.getSigningKeySet(null);
   2597             assertTrue(false); // should have thrown
   2598         } catch (NullPointerException e) {
   2599         }
   2600         try {
   2601             ks = pm.getSigningKeySet("keysets.test.bogus.package");
   2602             assertTrue(false); // should have thrown
   2603         } catch (IllegalArgumentException e) {
   2604         }
   2605         final InstallParams ip = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
   2606                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2607         try {
   2608             ks = pm.getSigningKeySet(otherPkgName);
   2609             assertTrue(false); // should have thrown
   2610         } catch (SecurityException e) {
   2611         } finally {
   2612             cleanUpInstall(ip);
   2613         }
   2614         ks = pm.getSigningKeySet(mContext.getPackageName());
   2615         assertNotNull(ks);
   2616     }
   2617 
   2618     /*
   2619      * testGetKeySetByAlias - same as getSigningKeySet, but for keysets defined
   2620      * by this package.
   2621      */
   2622     public void testGetKeySetByAlias() throws Exception {
   2623         PackageManager pm = getPm();
   2624         String mPkgName = mContext.getPackageName();
   2625         String otherPkgName = "com.android.frameworks.coretests.keysets_api";
   2626         KeySet ks;
   2627         try {
   2628             ks = pm.getKeySetByAlias(null, null);
   2629             assertTrue(false); // should have thrown
   2630         } catch (NullPointerException e) {
   2631         }
   2632         try {
   2633             ks = pm.getKeySetByAlias(null, "keysetBogus");
   2634             assertTrue(false); // should have thrown
   2635         } catch (NullPointerException e) {
   2636         }
   2637         try {
   2638             ks = pm.getKeySetByAlias("keysets.test.bogus.package", null);
   2639             assertTrue(false); // should have thrown
   2640         } catch (NullPointerException e) {
   2641         }
   2642         try {
   2643             ks = pm.getKeySetByAlias("keysets.test.bogus.package", "A");
   2644             assertTrue(false); // should have thrown
   2645         } catch(IllegalArgumentException e) {
   2646         }
   2647         try {
   2648             ks = pm.getKeySetByAlias(mPkgName, "keysetBogus");
   2649             assertTrue(false); // should have thrown
   2650         } catch(IllegalArgumentException e) {
   2651         }
   2652 
   2653         // make sure we can get a KeySet from our pkg
   2654         ks = pm.getKeySetByAlias(mPkgName, "A");
   2655         assertNotNull(ks);
   2656 
   2657         // and another
   2658         final InstallParams ip = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
   2659                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2660         try {
   2661             ks = pm.getKeySetByAlias(otherPkgName, "A");
   2662             assertNotNull(ks);
   2663         } finally {
   2664             cleanUpInstall(ip);
   2665         }
   2666     }
   2667 
   2668     public void testIsSignedBy() throws Exception {
   2669         PackageManager pm = getPm();
   2670         String mPkgName = mContext.getPackageName();
   2671         String otherPkgName = "com.android.frameworks.coretests.keysets_api";
   2672         KeySet mSigningKS = pm.getSigningKeySet(mPkgName);
   2673         KeySet mDefinedKS = pm.getKeySetByAlias(mPkgName, "A");
   2674 
   2675         try {
   2676             assertFalse(pm.isSignedBy(null, null));
   2677             assertTrue(false); // should have thrown
   2678         } catch (NullPointerException e) {
   2679         }
   2680         try {
   2681             assertFalse(pm.isSignedBy(null, mSigningKS));
   2682             assertTrue(false); // should have thrown
   2683         } catch (NullPointerException e) {
   2684         }
   2685         try {
   2686             assertFalse(pm.isSignedBy(mPkgName, null));
   2687             assertTrue(false); // should have thrown
   2688         } catch (NullPointerException e) {
   2689         }
   2690         try {
   2691             assertFalse(pm.isSignedBy("keysets.test.bogus.package", mDefinedKS));
   2692         } catch(IllegalArgumentException e) {
   2693         }
   2694         assertFalse(pm.isSignedBy(mPkgName, mDefinedKS));
   2695         assertFalse(pm.isSignedBy(mPkgName, new KeySet(new Binder())));
   2696         assertTrue(pm.isSignedBy(mPkgName, mSigningKS));
   2697 
   2698         final InstallParams ip1 = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
   2699                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2700         try {
   2701             assertFalse(pm.isSignedBy(otherPkgName, mDefinedKS));
   2702             assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
   2703         } finally {
   2704             cleanUpInstall(ip1);
   2705         }
   2706 
   2707         final InstallParams ip2 = installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
   2708                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2709         try {
   2710             assertTrue(pm.isSignedBy(otherPkgName, mDefinedKS));
   2711             assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
   2712         } finally {
   2713             cleanUpInstall(ip2);
   2714         }
   2715     }
   2716 
   2717     public void testIsSignedByExactly() throws Exception {
   2718         PackageManager pm = getPm();
   2719         String mPkgName = mContext.getPackageName();
   2720         String otherPkgName = "com.android.frameworks.coretests.keysets_api";
   2721         KeySet mSigningKS = pm.getSigningKeySet(mPkgName);
   2722         KeySet mDefinedKS = pm.getKeySetByAlias(mPkgName, "A");
   2723         try {
   2724             assertFalse(pm.isSignedBy(null, null));
   2725             assertTrue(false); // should have thrown
   2726         } catch (NullPointerException e) {
   2727         }
   2728         try {
   2729             assertFalse(pm.isSignedBy(null, mSigningKS));
   2730             assertTrue(false); // should have thrown
   2731         } catch (NullPointerException e) {
   2732         }
   2733         try {
   2734             assertFalse(pm.isSignedBy(mPkgName, null));
   2735             assertTrue(false); // should have thrown
   2736         } catch (NullPointerException e) {
   2737         }
   2738         try {
   2739             assertFalse(pm.isSignedByExactly("keysets.test.bogus.package", mDefinedKS));
   2740         } catch(IllegalArgumentException e) {
   2741         }
   2742         assertFalse(pm.isSignedByExactly(mPkgName, mDefinedKS));
   2743         assertFalse(pm.isSignedByExactly(mPkgName, new KeySet(new Binder())));
   2744         assertTrue(pm.isSignedByExactly(mPkgName, mSigningKS));
   2745 
   2746         final InstallParams ip1 = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
   2747                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2748         try {
   2749             assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
   2750             assertTrue(pm.isSignedByExactly(otherPkgName, mSigningKS));
   2751         } finally {
   2752             cleanUpInstall(ip1);
   2753         }
   2754 
   2755         final InstallParams ip2 = installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
   2756                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2757         try {
   2758             assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
   2759             assertFalse(pm.isSignedByExactly(otherPkgName, mSigningKS));
   2760         } finally {
   2761             cleanUpInstall(ip2);
   2762         }
   2763     }
   2764 
   2765 
   2766 
   2767     /**
   2768      * The following tests are related to testing the checkSignatures api.
   2769      */
   2770     private void checkSignatures(int apk1, int apk2, int expMatchResult) throws Exception {
   2771         checkSharedSignatures(apk1, apk2, true, false, -1, expMatchResult);
   2772     }
   2773 
   2774     @LargeTest
   2775     public void testCheckSignaturesAllMatch() throws Exception {
   2776         int apk1 = APP1_CERT1_CERT2;
   2777         int apk2 = APP2_CERT1_CERT2;
   2778         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
   2779     }
   2780 
   2781     @LargeTest
   2782     public void testCheckSignaturesNoMatch() throws Exception {
   2783         int apk1 = APP1_CERT1;
   2784         int apk2 = APP2_CERT2;
   2785         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
   2786     }
   2787 
   2788     @LargeTest
   2789     public void testCheckSignaturesSomeMatch1() throws Exception {
   2790         int apk1 = APP1_CERT1_CERT2;
   2791         int apk2 = APP2_CERT1;
   2792         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
   2793     }
   2794 
   2795     @LargeTest
   2796     public void testCheckSignaturesSomeMatch2() throws Exception {
   2797         int apk1 = APP1_CERT1_CERT2;
   2798         int apk2 = APP2_CERT2;
   2799         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
   2800     }
   2801 
   2802     @LargeTest
   2803     public void testCheckSignaturesMoreMatch() throws Exception {
   2804         int apk1 = APP1_CERT1;
   2805         int apk2 = APP2_CERT1_CERT2;
   2806         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
   2807     }
   2808 
   2809     @LargeTest
   2810     public void testCheckSignaturesUnknown() throws Exception {
   2811         int apk1 = APP1_CERT1_CERT2;
   2812         int apk2 = APP2_CERT1_CERT2;
   2813         String apk1Name = "install1.apk";
   2814         String apk2Name = "install2.apk";
   2815 
   2816         final InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
   2817                 false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2818         try {
   2819             PackageManager pm = mContext.getPackageManager();
   2820             // Delete app2
   2821             File filesDir = mContext.getFilesDir();
   2822             File outFile = new File(filesDir, apk2Name);
   2823             int rawResId = apk2;
   2824             Uri packageURI = getInstallablePackage(rawResId, outFile);
   2825             PackageParser.Package pkg = parsePackage(packageURI);
   2826             try {
   2827                 getPi().uninstall(pkg.packageName,
   2828                         PackageManager.DELETE_ALL_USERS,
   2829                         null /*statusReceiver*/);
   2830             } catch (IllegalArgumentException ignore) {
   2831             }
   2832             // Check signatures now
   2833             int match = mContext.getPackageManager().checkSignatures(
   2834                     ip.pkg.packageName, pkg.packageName);
   2835             assertEquals(PackageManager.SIGNATURE_UNKNOWN_PACKAGE, match);
   2836         } finally {
   2837             cleanUpInstall(ip);
   2838         }
   2839     }
   2840 
   2841     @LargeTest
   2842     public void testInstallNoCertificates() throws Exception {
   2843         int apk1 = APP1_UNSIGNED;
   2844         String apk1Name = "install1.apk";
   2845 
   2846         installFromRawResource(apk1Name, apk1, 0, false,
   2847                 true, PackageInstaller.STATUS_FAILURE_INVALID,
   2848                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2849     }
   2850 
   2851     /*
   2852      * The following tests are related to apps using shared uids signed with
   2853      * different certs.
   2854      */
   2855     private int SHARED1_UNSIGNED = R.raw.install_shared1_unsigned;
   2856 
   2857     private int SHARED1_CERT1 = R.raw.install_shared1_cert1;
   2858 
   2859     private int SHARED1_CERT2 = R.raw.install_shared1_cert2;
   2860 
   2861     private int SHARED1_CERT1_CERT2 = R.raw.install_shared1_cert1_cert2;
   2862 
   2863     private int SHARED2_UNSIGNED = R.raw.install_shared2_unsigned;
   2864 
   2865     private int SHARED2_CERT1 = R.raw.install_shared2_cert1;
   2866 
   2867     private int SHARED2_CERT2 = R.raw.install_shared2_cert2;
   2868 
   2869     private int SHARED2_CERT1_CERT2 = R.raw.install_shared2_cert1_cert2;
   2870 
   2871     private void checkSharedSignatures(int apk1, int apk2, boolean cleanUp, boolean fail,
   2872             int retCode, int expMatchResult) throws Exception {
   2873         String apk1Name = "install1.apk";
   2874         String apk2Name = "install2.apk";
   2875         PackageParser.Package pkg1 = getParsedPackage(apk1Name, apk1);
   2876         PackageParser.Package pkg2 = getParsedPackage(apk2Name, apk2);
   2877 
   2878         try {
   2879             // Clean up before testing first.
   2880             cleanUpInstall(pkg1.packageName);
   2881             cleanUpInstall(pkg2.packageName);
   2882             installFromRawResource(apk1Name, apk1, 0, false, false, -1,
   2883                     PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2884             if (fail) {
   2885                 installFromRawResource(apk2Name, apk2, 0, false, true, retCode,
   2886                         PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2887             } else {
   2888                 installFromRawResource(apk2Name, apk2, 0, false, false, -1,
   2889                         PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2890                 int match = mContext.getPackageManager().checkSignatures(pkg1.packageName,
   2891                         pkg2.packageName);
   2892                 assertEquals(expMatchResult, match);
   2893             }
   2894         } finally {
   2895             if (cleanUp) {
   2896                 cleanUpInstall(pkg1.packageName);
   2897                 cleanUpInstall(pkg2.packageName);
   2898             }
   2899         }
   2900     }
   2901 
   2902     @LargeTest
   2903     public void testCheckSignaturesSharedAllMatch() throws Exception {
   2904         int apk1 = SHARED1_CERT1_CERT2;
   2905         int apk2 = SHARED2_CERT1_CERT2;
   2906         boolean fail = false;
   2907         int retCode = -1;
   2908         int expMatchResult = PackageManager.SIGNATURE_MATCH;
   2909         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
   2910     }
   2911 
   2912     @LargeTest
   2913     public void testCheckSignaturesSharedNoMatch() throws Exception {
   2914         int apk1 = SHARED1_CERT1;
   2915         int apk2 = SHARED2_CERT2;
   2916         boolean fail = true;
   2917         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   2918         int expMatchResult = -1;
   2919         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
   2920     }
   2921 
   2922     /*
   2923      * Test that an app signed with cert1 and cert2 cannot be replaced when
   2924      * signed with cert1 alone.
   2925      */
   2926     @LargeTest
   2927     public void testCheckSignaturesSharedSomeMatch1() throws Exception {
   2928         int apk1 = SHARED1_CERT1_CERT2;
   2929         int apk2 = SHARED2_CERT1;
   2930         boolean fail = true;
   2931         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   2932         int expMatchResult = -1;
   2933         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
   2934     }
   2935 
   2936     /*
   2937      * Test that an app signed with cert1 and cert2 cannot be replaced when
   2938      * signed with cert2 alone.
   2939      */
   2940     @LargeTest
   2941     public void testCheckSignaturesSharedSomeMatch2() throws Exception {
   2942         int apk1 = SHARED1_CERT1_CERT2;
   2943         int apk2 = SHARED2_CERT2;
   2944         boolean fail = true;
   2945         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   2946         int expMatchResult = -1;
   2947         checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
   2948     }
   2949 
   2950     @LargeTest
   2951     public void testCheckSignaturesSharedUnknown() throws Exception {
   2952         int apk1 = SHARED1_CERT1_CERT2;
   2953         int apk2 = SHARED2_CERT1_CERT2;
   2954         String apk1Name = "install1.apk";
   2955         String apk2Name = "install2.apk";
   2956         InstallParams ip1 = null;
   2957 
   2958         try {
   2959             ip1 = installFromRawResource(apk1Name, apk1, 0, false,
   2960                     false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   2961             PackageManager pm = mContext.getPackageManager();
   2962             // Delete app2
   2963             PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
   2964             try {
   2965                 getPi().uninstall(
   2966                         pkg.packageName, PackageManager.DELETE_ALL_USERS, null /*statusReceiver*/);
   2967             } catch (IllegalArgumentException ignore) {
   2968             }
   2969             // Check signatures now
   2970             int match = mContext.getPackageManager().checkSignatures(
   2971                     ip1.pkg.packageName, pkg.packageName);
   2972             assertEquals(PackageManager.SIGNATURE_UNKNOWN_PACKAGE, match);
   2973         } finally {
   2974             if (ip1 != null) {
   2975                 cleanUpInstall(ip1);
   2976             }
   2977         }
   2978     }
   2979 
   2980     @LargeTest
   2981     public void testReplaceFirstSharedMatchAllCerts() throws Exception {
   2982         int apk1 = SHARED1_CERT1;
   2983         int apk2 = SHARED2_CERT1;
   2984         int rapk1 = SHARED1_CERT1;
   2985         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
   2986         replaceCerts(apk1, rapk1, true, false, -1);
   2987     }
   2988 
   2989     @LargeTest
   2990     public void testReplaceSecondSharedMatchAllCerts() throws Exception {
   2991         int apk1 = SHARED1_CERT1;
   2992         int apk2 = SHARED2_CERT1;
   2993         int rapk2 = SHARED2_CERT1;
   2994         checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
   2995         replaceCerts(apk2, rapk2, true, false, -1);
   2996     }
   2997 
   2998     @LargeTest
   2999     public void testReplaceFirstSharedMatchSomeCerts() throws Exception {
   3000         int apk1 = SHARED1_CERT1_CERT2;
   3001         int apk2 = SHARED2_CERT1_CERT2;
   3002         int rapk1 = SHARED1_CERT1;
   3003         boolean fail = true;
   3004         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   3005         checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
   3006         installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
   3007                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3008     }
   3009 
   3010     @LargeTest
   3011     public void testReplaceSecondSharedMatchSomeCerts() throws Exception {
   3012         int apk1 = SHARED1_CERT1_CERT2;
   3013         int apk2 = SHARED2_CERT1_CERT2;
   3014         int rapk2 = SHARED2_CERT1;
   3015         boolean fail = true;
   3016         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   3017         checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
   3018         installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
   3019                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3020     }
   3021 
   3022     @LargeTest
   3023     public void testReplaceFirstSharedMatchNoCerts() throws Exception {
   3024         int apk1 = SHARED1_CERT1;
   3025         int apk2 = SHARED2_CERT1;
   3026         int rapk1 = SHARED1_CERT2;
   3027         boolean fail = true;
   3028         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   3029         checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
   3030         installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
   3031                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3032     }
   3033 
   3034     @LargeTest
   3035     public void testReplaceSecondSharedMatchNoCerts() throws Exception {
   3036         int apk1 = SHARED1_CERT1;
   3037         int apk2 = SHARED2_CERT1;
   3038         int rapk2 = SHARED2_CERT2;
   3039         boolean fail = true;
   3040         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   3041         checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
   3042         installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
   3043                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3044     }
   3045 
   3046     @LargeTest
   3047     public void testReplaceFirstSharedMatchMoreCerts() throws Exception {
   3048         int apk1 = SHARED1_CERT1;
   3049         int apk2 = SHARED2_CERT1;
   3050         int rapk1 = SHARED1_CERT1_CERT2;
   3051         boolean fail = true;
   3052         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   3053         checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
   3054         installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
   3055                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3056     }
   3057 
   3058     @LargeTest
   3059     public void testReplaceSecondSharedMatchMoreCerts() throws Exception {
   3060         int apk1 = SHARED1_CERT1;
   3061         int apk2 = SHARED2_CERT1;
   3062         int rapk2 = SHARED2_CERT1_CERT2;
   3063         boolean fail = true;
   3064         int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
   3065         checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
   3066         installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
   3067                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3068     }
   3069 
   3070     /**
   3071      * Unknown features should be allowed to install. This prevents older phones
   3072      * from rejecting new packages that specify features that didn't exist when
   3073      * an older phone existed. All older phones are assumed to have those
   3074      * features.
   3075      * <p>
   3076      * Right now we allow all packages to be installed regardless of their
   3077      * features.
   3078      */
   3079     @LargeTest
   3080     public void testUsesFeatureUnknownFeature() throws Exception {
   3081         int retCode = PackageManager.INSTALL_SUCCEEDED;
   3082         installFromRawResource("install.apk", R.raw.install_uses_feature, 0, true, false, retCode,
   3083                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3084     }
   3085 
   3086     @LargeTest
   3087     public void testInstallNonexistentFile() throws Exception {
   3088         int retCode = PackageInstaller.STATUS_FAILURE_INVALID;
   3089         File invalidFile = new File("/nonexistent-file.apk");
   3090         invokeInstallPackageFail(Uri.fromFile(invalidFile), 0, retCode);
   3091     }
   3092 
   3093     @SmallTest
   3094     public void testGetVerifierDeviceIdentity() throws Exception {
   3095         PackageManager pm = getPm();
   3096         VerifierDeviceIdentity id = pm.getVerifierDeviceIdentity();
   3097 
   3098         assertNotNull("Verifier device identity should not be null", id);
   3099     }
   3100 
   3101     public void testGetInstalledPackages() throws Exception {
   3102         List<PackageInfo> packages = getPm().getInstalledPackages(0);
   3103         assertNotNull("installed packages cannot be null", packages);
   3104         assertTrue("installed packages cannot be empty", packages.size() > 0);
   3105     }
   3106 
   3107     public void testGetUnInstalledPackages() throws Exception {
   3108         List<PackageInfo> packages = getPm().getInstalledPackages(
   3109                 PackageManager.MATCH_UNINSTALLED_PACKAGES);
   3110         assertNotNull("installed packages cannot be null", packages);
   3111         assertTrue("installed packages cannot be empty", packages.size() > 0);
   3112     }
   3113 
   3114     /**
   3115      * Test that getInstalledPackages returns all the data specified in flags.
   3116      */
   3117     public void testGetInstalledPackagesAll() throws Exception {
   3118         final int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
   3119                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
   3120                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
   3121                 | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
   3122                 | PackageManager.GET_SIGNATURES | PackageManager.MATCH_UNINSTALLED_PACKAGES;
   3123 
   3124         final InstallParams ip =
   3125                 installFromRawResource("install.apk", R.raw.install_complete_package_info,
   3126                         0 /*flags*/, false /*cleanUp*/, false /*fail*/, -1 /*result*/,
   3127                         PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   3128         try {
   3129             final List<PackageInfo> packages = getPm().getInstalledPackages(flags);
   3130             assertNotNull("installed packages cannot be null", packages);
   3131             assertTrue("installed packages cannot be empty", packages.size() > 0);
   3132 
   3133             PackageInfo packageInfo = null;
   3134 
   3135             // Find the package with all components specified in the AndroidManifest
   3136             // to ensure no null values
   3137             for (PackageInfo pi : packages) {
   3138                 if ("com.android.frameworks.coretests.install_complete_package_info"
   3139                         .equals(pi.packageName)) {
   3140                     packageInfo = pi;
   3141                     break;
   3142                 }
   3143             }
   3144             assertNotNull("activities should not be null", packageInfo.activities);
   3145             assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
   3146             assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
   3147             assertNotNull("permissions should not be null", packageInfo.permissions);
   3148             assertNotNull("providers should not be null", packageInfo.providers);
   3149             assertNotNull("receivers should not be null", packageInfo.receivers);
   3150             assertNotNull("services should not be null", packageInfo.services);
   3151             assertNotNull("signatures should not be null", packageInfo.signatures);
   3152         } finally {
   3153             cleanUpInstall(ip);
   3154         }
   3155     }
   3156 
   3157     /**
   3158      * Test that getInstalledPackages returns all the data specified in
   3159      * flags when the GET_UNINSTALLED_PACKAGES flag is set.
   3160      */
   3161     public void testGetUnInstalledPackagesAll() throws Exception {
   3162         final int flags = PackageManager.MATCH_UNINSTALLED_PACKAGES
   3163                 | PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
   3164                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
   3165                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
   3166                 | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
   3167                 | PackageManager.GET_SIGNATURES;
   3168 
   3169         // first, install the package
   3170         final InstallParams ip =
   3171                 installFromRawResource("install.apk", R.raw.install_complete_package_info,
   3172                         0 /*flags*/, false /*cleanUp*/, false /*fail*/, -1 /*result*/,
   3173                         PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
   3174         try {
   3175             // then, remove it, keeping it's data around
   3176             final GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
   3177             invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
   3178 
   3179             final List<PackageInfo> packages = getPm().getInstalledPackages(flags);
   3180             assertNotNull("installed packages cannot be null", packages);
   3181             assertTrue("installed packages cannot be empty", packages.size() > 0);
   3182 
   3183             PackageInfo packageInfo = null;
   3184 
   3185             // Find the package with all components specified in the AndroidManifest
   3186             // to ensure no null values
   3187             for (PackageInfo pi : packages) {
   3188                 if ("com.android.frameworks.coretests.install_complete_package_info"
   3189                         .equals(pi.packageName)) {
   3190                     packageInfo = pi;
   3191                     break;
   3192                 }
   3193             }
   3194             assertNotNull("activities should not be null", packageInfo.activities);
   3195             assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
   3196             assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
   3197             assertNotNull("permissions should not be null", packageInfo.permissions);
   3198             assertNotNull("providers should not be null", packageInfo.providers);
   3199             assertNotNull("receivers should not be null", packageInfo.receivers);
   3200             assertNotNull("services should not be null", packageInfo.services);
   3201             assertNotNull("signatures should not be null", packageInfo.signatures);
   3202         } finally {
   3203             cleanUpInstall(ip);
   3204         }
   3205     }
   3206 
   3207     @Suppress
   3208     public void testInstall_BadDex_CleanUp() throws Exception {
   3209         int retCode = PackageInstaller.STATUS_FAILURE_INVALID;
   3210         installFromRawResource("install.apk", R.raw.install_bad_dex, 0, true, true, retCode,
   3211                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
   3212     }
   3213 
   3214     private static class TestDexModuleRegisterCallback
   3215             extends PackageManager.DexModuleRegisterCallback {
   3216         private String mDexModulePath = null;
   3217         private boolean mSuccess = false;
   3218         private String mMessage = null;
   3219         CountDownLatch doneSignal = new CountDownLatch(1);
   3220 
   3221         @Override
   3222         public void onDexModuleRegistered(String dexModulePath, boolean success, String message) {
   3223             mDexModulePath = dexModulePath;
   3224             mSuccess = success;
   3225             mMessage = message;
   3226             doneSignal.countDown();
   3227         }
   3228 
   3229         boolean waitTillDone() {
   3230             long startTime = System.currentTimeMillis();
   3231             while (System.currentTimeMillis() - startTime < MAX_WAIT_TIME) {
   3232                 try {
   3233                     return doneSignal.await(MAX_WAIT_TIME, TimeUnit.MILLISECONDS);
   3234                 } catch (InterruptedException e) {
   3235                     Log.i(TAG, "Interrupted during sleep", e);
   3236                 }
   3237             }
   3238             return false;
   3239         }
   3240 
   3241     }
   3242 
   3243     // Verify that the base code path cannot be registered.
   3244     public void testRegisterDexModuleBaseCode() throws Exception {
   3245         PackageManager pm = getPm();
   3246         ApplicationInfo info = getContext().getApplicationInfo();
   3247         TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
   3248         pm.registerDexModule(info.getBaseCodePath(), callback);
   3249         assertTrue(callback.waitTillDone());
   3250         assertEquals(info.getBaseCodePath(), callback.mDexModulePath);
   3251         assertFalse("BaseCodePath should not be registered", callback.mSuccess);
   3252     }
   3253 
   3254     // Verify thatmodules which are not own by the calling package are not registered.
   3255     public void testRegisterDexModuleNotOwningModule() throws Exception {
   3256         TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
   3257         String moduleBelongingToOtherPackage = "/data/user/0/com.google.android.gms/module.apk";
   3258         getPm().registerDexModule(moduleBelongingToOtherPackage, callback);
   3259         assertTrue(callback.waitTillDone());
   3260         assertEquals(moduleBelongingToOtherPackage, callback.mDexModulePath);
   3261         assertTrue(callback.waitTillDone());
   3262         assertFalse("Only modules belonging to the calling package can be registered",
   3263                 callback.mSuccess);
   3264     }
   3265 
   3266     // Verify that modules owned by the package are successfully registered.
   3267     public void testRegisterDexModuleSuccessfully() throws Exception {
   3268         ApplicationInfo info = getContext().getApplicationInfo();
   3269         // Copy the main apk into the data folder and use it as a "module".
   3270         File dexModuleDir = new File(info.dataDir, "module-dir");
   3271         File dexModule = new File(dexModuleDir, "module.apk");
   3272         try {
   3273             assertNotNull(FileUtils.createDir(
   3274                     dexModuleDir.getParentFile(), dexModuleDir.getName()));
   3275             Files.copy(Paths.get(info.getBaseCodePath()), dexModule.toPath(),
   3276                     StandardCopyOption.REPLACE_EXISTING);
   3277             TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
   3278             getPm().registerDexModule(dexModule.toString(), callback);
   3279             assertTrue(callback.waitTillDone());
   3280             assertEquals(dexModule.toString(), callback.mDexModulePath);
   3281             assertTrue(callback.waitTillDone());
   3282             assertTrue(callback.mMessage, callback.mSuccess);
   3283 
   3284             // NOTE:
   3285             // This actually verifies internal behaviour which might change. It's not
   3286             // ideal but it's the best we can do since there's no other place we can currently
   3287             // write a better test.
   3288             for(String isa : getAppDexInstructionSets(info)) {
   3289                 Files.exists(Paths.get(dexModuleDir.toString(), "oat", isa, "module.odex"));
   3290                 Files.exists(Paths.get(dexModuleDir.toString(), "oat", isa, "module.vdex"));
   3291             }
   3292         } finally {
   3293             FileUtils.deleteContentsAndDir(dexModuleDir);
   3294         }
   3295     }
   3296 
   3297     // If the module does not exist on disk we should get a failure.
   3298     public void testRegisterDexModuleNotExists() throws Exception {
   3299         ApplicationInfo info = getContext().getApplicationInfo();
   3300         String nonExistentApk = Paths.get(info.dataDir, "non-existent.apk").toString();
   3301         TestDexModuleRegisterCallback callback = new TestDexModuleRegisterCallback();
   3302         getPm().registerDexModule(nonExistentApk, callback);
   3303         assertTrue(callback.waitTillDone());
   3304         assertEquals(nonExistentApk, callback.mDexModulePath);
   3305         assertTrue(callback.waitTillDone());
   3306         assertFalse("DexModule registration should fail", callback.mSuccess);
   3307     }
   3308 
   3309     // Copied from com.android.server.pm.InstructionSets because we don't have access to it here.
   3310     private static String[] getAppDexInstructionSets(ApplicationInfo info) {
   3311         if (info.primaryCpuAbi != null) {
   3312             if (info.secondaryCpuAbi != null) {
   3313                 return new String[] {
   3314                         VMRuntime.getInstructionSet(info.primaryCpuAbi),
   3315                         VMRuntime.getInstructionSet(info.secondaryCpuAbi) };
   3316             } else {
   3317                 return new String[] {
   3318                         VMRuntime.getInstructionSet(info.primaryCpuAbi) };
   3319             }
   3320         }
   3321 
   3322         return new String[] { VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]) };
   3323     }
   3324 
   3325     /*---------- Recommended install location tests ----*/
   3326     /*
   3327      * TODO's
   3328      * check version numbers for upgrades
   3329      * check permissions of installed packages
   3330      * how to do tests on updated system apps?
   3331      * verify updates to system apps cannot be installed on the sdcard.
   3332      */
   3333 }
   3334