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