1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm;
18 
19 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
20 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
21 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
22 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
23 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
24 
25 import android.accounts.IAccountManager;
26 import android.app.ActivityManager;
27 import android.app.ActivityManagerInternal;
28 import android.app.role.IRoleManager;
29 import android.app.role.RoleManager;
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.IIntentReceiver;
33 import android.content.IIntentSender;
34 import android.content.Intent;
35 import android.content.IntentSender;
36 import android.content.pm.ApplicationInfo;
37 import android.content.pm.FeatureInfo;
38 import android.content.pm.IPackageDataObserver;
39 import android.content.pm.IPackageInstaller;
40 import android.content.pm.IPackageManager;
41 import android.content.pm.InstrumentationInfo;
42 import android.content.pm.ModuleInfo;
43 import android.content.pm.PackageInfo;
44 import android.content.pm.PackageInstaller;
45 import android.content.pm.PackageInstaller.SessionInfo;
46 import android.content.pm.PackageInstaller.SessionParams;
47 import android.content.pm.PackageItemInfo;
48 import android.content.pm.PackageManager;
49 import android.content.pm.PackageManager.NameNotFoundException;
50 import android.content.pm.PackageManagerInternal;
51 import android.content.pm.PackageParser;
52 import android.content.pm.PackageParser.ApkLite;
53 import android.content.pm.PackageParser.PackageLite;
54 import android.content.pm.PackageParser.PackageParserException;
55 import android.content.pm.ParceledListSlice;
56 import android.content.pm.PermissionGroupInfo;
57 import android.content.pm.PermissionInfo;
58 import android.content.pm.ResolveInfo;
59 import android.content.pm.SuspendDialogInfo;
60 import android.content.pm.UserInfo;
61 import android.content.pm.VersionedPackage;
62 import android.content.pm.dex.ArtManager;
63 import android.content.pm.dex.DexMetadataHelper;
64 import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
65 import android.content.res.AssetManager;
66 import android.content.res.Resources;
67 import android.content.rollback.IRollbackManager;
68 import android.content.rollback.PackageRollbackInfo;
69 import android.content.rollback.RollbackInfo;
70 import android.content.rollback.RollbackManager;
71 import android.net.Uri;
72 import android.os.Binder;
73 import android.os.Build;
74 import android.os.Bundle;
75 import android.os.IBinder;
76 import android.os.IUserManager;
77 import android.os.ParcelFileDescriptor;
78 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
79 import android.os.PersistableBundle;
80 import android.os.Process;
81 import android.os.RemoteCallback;
82 import android.os.RemoteException;
83 import android.os.ServiceManager;
84 import android.os.ShellCommand;
85 import android.os.SystemClock;
86 import android.os.SystemProperties;
87 import android.os.UserHandle;
88 import android.os.UserManager;
89 import android.os.storage.StorageManager;
90 import android.system.ErrnoException;
91 import android.system.Os;
92 import android.text.TextUtils;
93 import android.text.format.DateUtils;
94 import android.util.ArraySet;
95 import android.util.PrintWriterPrinter;
96 import android.util.SparseArray;
97 
98 import com.android.internal.content.PackageHelper;
99 import com.android.internal.util.ArrayUtils;
100 import com.android.internal.util.IndentingPrintWriter;
101 import com.android.server.LocalServices;
102 import com.android.server.SystemConfig;
103 
104 import dalvik.system.DexFile;
105 
106 import libcore.io.IoUtils;
107 import libcore.io.Streams;
108 
109 import java.io.File;
110 import java.io.FileOutputStream;
111 import java.io.IOException;
112 import java.io.InputStream;
113 import java.io.OutputStream;
114 import java.io.PrintWriter;
115 import java.net.URISyntaxException;
116 import java.util.ArrayList;
117 import java.util.Collections;
118 import java.util.Comparator;
119 import java.util.LinkedList;
120 import java.util.List;
121 import java.util.Map;
122 import java.util.Objects;
123 import java.util.WeakHashMap;
124 import java.util.concurrent.CompletableFuture;
125 import java.util.concurrent.CountDownLatch;
126 import java.util.concurrent.LinkedBlockingQueue;
127 import java.util.concurrent.TimeUnit;
128 
129 class PackageManagerShellCommand extends ShellCommand {
130     /** Path for streaming APK content */
131     private static final String STDIN_PATH = "-";
132     /** Path where ART profiles snapshots are dumped for the shell user */
133     private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
134     private static final int DEFAULT_WAIT_MS = 60 * 1000;
135 
136     final IPackageManager mInterface;
137     final private WeakHashMap<String, Resources> mResourceCache =
138             new WeakHashMap<String, Resources>();
139     int mTargetUser;
140     boolean mBrief;
141     boolean mComponents;
142     int mQueryFlags;
143 
PackageManagerShellCommand(PackageManagerService service)144     PackageManagerShellCommand(PackageManagerService service) {
145         mInterface = service;
146     }
147 
148     @Override
onCommand(String cmd)149     public int onCommand(String cmd) {
150         if (cmd == null) {
151             return handleDefaultCommands(cmd);
152         }
153 
154         final PrintWriter pw = getOutPrintWriter();
155         try {
156             switch(cmd) {
157                 case "path":
158                     return runPath();
159                 case "dump":
160                     return runDump();
161                 case "list":
162                     return runList();
163                 case "resolve-activity":
164                     return runResolveActivity();
165                 case "query-activities":
166                     return runQueryIntentActivities();
167                 case "query-services":
168                     return runQueryIntentServices();
169                 case "query-receivers":
170                     return runQueryIntentReceivers();
171                 case "install":
172                     return runInstall();
173                 case "install-abandon":
174                 case "install-destroy":
175                     return runInstallAbandon();
176                 case "install-commit":
177                     return runInstallCommit();
178                 case "install-create":
179                     return runInstallCreate();
180                 case "install-remove":
181                     return runInstallRemove();
182                 case "install-write":
183                     return runInstallWrite();
184                 case "install-existing":
185                     return runInstallExisting();
186                 case "set-install-location":
187                     return runSetInstallLocation();
188                 case "get-install-location":
189                     return runGetInstallLocation();
190                 case "install-add-session":
191                     return runInstallAddSession();
192                 case "move-package":
193                     return runMovePackage();
194                 case "move-primary-storage":
195                     return runMovePrimaryStorage();
196                 case "compile":
197                     return runCompile();
198                 case "reconcile-secondary-dex-files":
199                     return runreconcileSecondaryDexFiles();
200                 case "force-dex-opt":
201                     return runForceDexOpt();
202                 case "bg-dexopt-job":
203                     return runDexoptJob();
204                 case "dump-profiles":
205                     return runDumpProfiles();
206                 case "snapshot-profile":
207                     return runSnapshotProfile();
208                 case "uninstall":
209                     return runUninstall();
210                 case "clear":
211                     return runClear();
212                 case "enable":
213                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
214                 case "disable":
215                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
216                 case "disable-user":
217                     return runSetEnabledSetting(
218                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
219                 case "disable-until-used":
220                     return runSetEnabledSetting(
221                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
222                 case "default-state":
223                     return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
224                 case "hide":
225                     return runSetHiddenSetting(true);
226                 case "unhide":
227                     return runSetHiddenSetting(false);
228                 case "suspend":
229                     return runSuspend(true);
230                 case "unsuspend":
231                     return runSuspend(false);
232                 case "grant":
233                     return runGrantRevokePermission(true);
234                 case "revoke":
235                     return runGrantRevokePermission(false);
236                 case "reset-permissions":
237                     return runResetPermissions();
238                 case "set-permission-enforced":
239                     return runSetPermissionEnforced();
240                 case "get-privapp-permissions":
241                     return runGetPrivappPermissions();
242                 case "get-privapp-deny-permissions":
243                     return runGetPrivappDenyPermissions();
244                 case "get-oem-permissions":
245                     return runGetOemPermissions();
246                 case "set-app-link":
247                     return runSetAppLink();
248                 case "get-app-link":
249                     return runGetAppLink();
250                 case "trim-caches":
251                     return runTrimCaches();
252                 case "create-user":
253                     return runCreateUser();
254                 case "remove-user":
255                     return runRemoveUser();
256                 case "set-user-restriction":
257                     return runSetUserRestriction();
258                 case "get-max-users":
259                     return runGetMaxUsers();
260                 case "get-max-running-users":
261                     return runGetMaxRunningUsers();
262                 case "set-home-activity":
263                     return runSetHomeActivity();
264                 case "set-installer":
265                     return runSetInstaller();
266                 case "get-instantapp-resolver":
267                     return runGetInstantAppResolver();
268                 case "has-feature":
269                     return runHasFeature();
270                 case "set-harmful-app-warning":
271                     return runSetHarmfulAppWarning();
272                 case "get-harmful-app-warning":
273                     return runGetHarmfulAppWarning();
274                 case "get-stagedsessions":
275                     return runListStagedSessions();
276                 case "uninstall-system-updates":
277                     return uninstallSystemUpdates();
278                 case "rollback-app":
279                     return runRollbackApp();
280                 case "get-moduleinfo":
281                     return runGetModuleInfo();
282                 default: {
283                     String nextArg = getNextArg();
284                     if (nextArg == null) {
285                         if (cmd.equalsIgnoreCase("-l")) {
286                             return runListPackages(false);
287                         } else if (cmd.equalsIgnoreCase("-lf")) {
288                             return runListPackages(true);
289                         }
290                     } else if (getNextArg() == null) {
291                         if (cmd.equalsIgnoreCase("-p")) {
292                             return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM);
293                         }
294                     }
295                     return handleDefaultCommands(cmd);
296                 }
297             }
298         } catch (RemoteException e) {
299             pw.println("Remote exception: " + e);
300         }
301         return -1;
302     }
303 
304     /**
305      * Shows module info
306      *
307      * Usage: get-moduleinfo [--all | --installed] [module-name]
308      * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz
309      */
runGetModuleInfo()310     private int runGetModuleInfo() {
311         final PrintWriter pw = getOutPrintWriter();
312         int flags = 0;
313 
314         String opt;
315         while ((opt = getNextOption()) != null) {
316             switch (opt) {
317                 case "--all":
318                     flags |= PackageManager.MATCH_ALL;
319                     break;
320                 case "--installed":
321                     break;
322                 default:
323                     pw.println("Error: Unknown option: " + opt);
324                     return -1;
325             }
326         }
327 
328         String moduleName = getNextArg();
329         try {
330             if (moduleName != null) {
331                 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags);
332                 pw.println(m.toString() + " packageName: " + m.getPackageName());
333 
334             } else {
335                 List<ModuleInfo> modules = mInterface.getInstalledModules(flags);
336                 for (ModuleInfo m: modules) {
337                     pw.println(m.toString() + " packageName: " + m.getPackageName());
338                 }
339             }
340         } catch (RemoteException e) {
341             pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
342             return -1;
343         }
344         return 1;
345     }
346 
uninstallSystemUpdates()347     private int uninstallSystemUpdates() {
348         final PrintWriter pw = getOutPrintWriter();
349         List<String> failedUninstalls = new LinkedList<>();
350         try {
351             final ParceledListSlice<ApplicationInfo> packages =
352                     mInterface.getInstalledApplications(
353                             PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
354             final IPackageInstaller installer = mInterface.getPackageInstaller();
355             List<ApplicationInfo> list = packages.getList();
356             for (ApplicationInfo info : list) {
357                 if (info.isUpdatedSystemApp()) {
358                     pw.println("Uninstalling updates to " + info.packageName + "...");
359                     final LocalIntentReceiver receiver = new LocalIntentReceiver();
360                     installer.uninstall(new VersionedPackage(info.packageName,
361                                     info.versionCode), null /*callerPackageName*/, 0 /* flags */,
362                             receiver.getIntentSender(), 0);
363 
364                     final Intent result = receiver.getResult();
365                     final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
366                             PackageInstaller.STATUS_FAILURE);
367                     if (status != PackageInstaller.STATUS_SUCCESS) {
368                         failedUninstalls.add(info.packageName);
369                     }
370                 }
371             }
372         } catch (RemoteException e) {
373             pw.println("Failure ["
374                     + e.getClass().getName() + " - "
375                     + e.getMessage() + "]");
376             return 0;
377         }
378         if (!failedUninstalls.isEmpty()) {
379             pw.println("Failure [Couldn't uninstall packages: "
380                     + TextUtils.join(", ", failedUninstalls)
381                     + "]");
382             return 0;
383         }
384         pw.println("Success");
385         return 1;
386     }
387 
runRollbackApp()388     private int runRollbackApp() {
389         final PrintWriter pw = getOutPrintWriter();
390 
391         final String packageName = getNextArgRequired();
392         if (packageName == null) {
393             pw.println("Error: package name not specified");
394             return 1;
395         }
396 
397         final LocalIntentReceiver receiver = new LocalIntentReceiver();
398         try {
399             IRollbackManager rm = IRollbackManager.Stub.asInterface(
400                     ServiceManager.getService(Context.ROLLBACK_SERVICE));
401 
402             RollbackInfo rollback = null;
403             for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
404                 for (PackageRollbackInfo info : r.getPackages()) {
405                     if (packageName.equals(info.getPackageName())) {
406                         rollback = r;
407                         break;
408                     }
409                 }
410             }
411 
412             if (rollback == null) {
413                 pw.println("No available rollbacks for: " + packageName);
414                 return 1;
415             }
416 
417             rm.commitRollback(rollback.getRollbackId(),
418                     ParceledListSlice.<VersionedPackage>emptyList(),
419                     "com.android.shell", receiver.getIntentSender());
420         } catch (RemoteException re) {
421             // Cannot happen.
422         }
423 
424         final Intent result = receiver.getResult();
425         final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
426                 RollbackManager.STATUS_FAILURE);
427         if (status == RollbackManager.STATUS_SUCCESS) {
428             pw.println("Success");
429             return 0;
430         } else {
431             pw.println("Failure ["
432                     + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
433             return 1;
434         }
435     }
436 
setParamsSize(InstallParams params, String inPath)437     private void setParamsSize(InstallParams params, String inPath) {
438         if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
439             final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
440             if (fd == null) {
441                 getErrPrintWriter().println("Error: Can't open file: " + inPath);
442                 throw new IllegalArgumentException("Error: Can't open file: " + inPath);
443             }
444             try {
445                 ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0);
446                 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
447                         null, null);
448                 params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
449                         pkgLite, params.sessionParams.abiOverride, fd.getFileDescriptor()));
450             } catch (PackageParserException | IOException e) {
451                 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);
452                 throw new IllegalArgumentException(
453                         "Error: Failed to parse APK file: " + inPath, e);
454             } finally {
455                 try {
456                     fd.close();
457                 } catch (IOException e) {
458                 }
459             }
460         }
461     }
462     /**
463      * Displays the package file for a package.
464      * @param pckg
465      */
displayPackageFilePath(String pckg, int userId)466     private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
467         PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
468         if (info != null && info.applicationInfo != null) {
469             final PrintWriter pw = getOutPrintWriter();
470             pw.print("package:");
471             pw.println(info.applicationInfo.sourceDir);
472             if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
473                 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
474                     pw.print("package:");
475                     pw.println(splitSourceDir);
476                 }
477             }
478             return 0;
479         }
480         return 1;
481     }
482 
runPath()483     private int runPath() throws RemoteException {
484         int userId = UserHandle.USER_SYSTEM;
485         String option = getNextOption();
486         if (option != null && option.equals("--user")) {
487             userId = UserHandle.parseUserArg(getNextArgRequired());
488         }
489 
490         String pkg = getNextArgRequired();
491         if (pkg == null) {
492             getErrPrintWriter().println("Error: no package specified");
493             return 1;
494         }
495         return displayPackageFilePath(pkg, userId);
496     }
497 
runList()498     private int runList() throws RemoteException {
499         final PrintWriter pw = getOutPrintWriter();
500         final String type = getNextArg();
501         if (type == null) {
502             pw.println("Error: didn't specify type of data to list");
503             return -1;
504         }
505         switch(type) {
506             case "features":
507                 return runListFeatures();
508             case "instrumentation":
509                 return runListInstrumentation();
510             case "libraries":
511                 return runListLibraries();
512             case "package":
513             case "packages":
514                 return runListPackages(false /*showSourceDir*/);
515             case "permission-groups":
516                 return runListPermissionGroups();
517             case "permissions":
518                 return runListPermissions();
519             case "staged-sessions":
520                 return runListStagedSessions();
521             case "users":
522                 ServiceManager.getService("user").shellCommand(
523                         getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
524                         new String[] { "list" }, getShellCallback(), adoptResultReceiver());
525                 return 0;
526         }
527         pw.println("Error: unknown list type '" + type + "'");
528         return -1;
529     }
530 
runListFeatures()531     private int runListFeatures() throws RemoteException {
532         final PrintWriter pw = getOutPrintWriter();
533         final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
534 
535         // sort by name
536         Collections.sort(list, new Comparator<FeatureInfo>() {
537             public int compare(FeatureInfo o1, FeatureInfo o2) {
538                 if (o1.name == o2.name) return 0;
539                 if (o1.name == null) return -1;
540                 if (o2.name == null) return 1;
541                 return o1.name.compareTo(o2.name);
542             }
543         });
544 
545         final int count = (list != null) ? list.size() : 0;
546         for (int p = 0; p < count; p++) {
547             FeatureInfo fi = list.get(p);
548             pw.print("feature:");
549             if (fi.name != null) {
550                 pw.print(fi.name);
551                 if (fi.version > 0) {
552                     pw.print("=");
553                     pw.print(fi.version);
554                 }
555                 pw.println();
556             } else {
557                 pw.println("reqGlEsVersion=0x"
558                         + Integer.toHexString(fi.reqGlEsVersion));
559             }
560         }
561         return 0;
562     }
563 
runListInstrumentation()564     private int runListInstrumentation() throws RemoteException {
565         final PrintWriter pw = getOutPrintWriter();
566         boolean showSourceDir = false;
567         String targetPackage = null;
568 
569         try {
570             String opt;
571             while ((opt = getNextArg()) != null) {
572                 switch (opt) {
573                     case "-f":
574                         showSourceDir = true;
575                         break;
576                     default:
577                         if (opt.charAt(0) != '-') {
578                             targetPackage = opt;
579                         } else {
580                             pw.println("Error: Unknown option: " + opt);
581                             return -1;
582                         }
583                         break;
584                 }
585             }
586         } catch (RuntimeException ex) {
587             pw.println("Error: " + ex.toString());
588             return -1;
589         }
590 
591         final List<InstrumentationInfo> list =
592                 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
593 
594         // sort by target package
595         Collections.sort(list, new Comparator<InstrumentationInfo>() {
596             public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
597                 return o1.targetPackage.compareTo(o2.targetPackage);
598             }
599         });
600 
601         final int count = (list != null) ? list.size() : 0;
602         for (int p = 0; p < count; p++) {
603             final InstrumentationInfo ii = list.get(p);
604             pw.print("instrumentation:");
605             if (showSourceDir) {
606                 pw.print(ii.sourceDir);
607                 pw.print("=");
608             }
609             final ComponentName cn = new ComponentName(ii.packageName, ii.name);
610             pw.print(cn.flattenToShortString());
611             pw.print(" (target=");
612             pw.print(ii.targetPackage);
613             pw.println(")");
614         }
615         return 0;
616     }
617 
runListLibraries()618     private int runListLibraries() throws RemoteException {
619         final PrintWriter pw = getOutPrintWriter();
620         final List<String> list = new ArrayList<String>();
621         final String[] rawList = mInterface.getSystemSharedLibraryNames();
622         for (int i = 0; i < rawList.length; i++) {
623             list.add(rawList[i]);
624         }
625 
626         // sort by name
627         Collections.sort(list, new Comparator<String>() {
628             public int compare(String o1, String o2) {
629                 if (o1 == o2) return 0;
630                 if (o1 == null) return -1;
631                 if (o2 == null) return 1;
632                 return o1.compareTo(o2);
633             }
634         });
635 
636         final int count = (list != null) ? list.size() : 0;
637         for (int p = 0; p < count; p++) {
638             String lib = list.get(p);
639             pw.print("library:");
640             pw.println(lib);
641         }
642         return 0;
643     }
644 
runListPackages(boolean showSourceDir)645     private int runListPackages(boolean showSourceDir) throws RemoteException {
646         final PrintWriter pw = getOutPrintWriter();
647         int getFlags = 0;
648         boolean listDisabled = false, listEnabled = false;
649         boolean listSystem = false, listThirdParty = false;
650         boolean listInstaller = false;
651         boolean showUid = false;
652         boolean showVersionCode = false;
653         boolean listApexOnly = false;
654         int uid = -1;
655         int userId = UserHandle.USER_SYSTEM;
656         try {
657             String opt;
658             while ((opt = getNextOption()) != null) {
659                 switch (opt) {
660                     case "-d":
661                         listDisabled = true;
662                         break;
663                     case "-e":
664                         listEnabled = true;
665                         break;
666                     case "-a":
667                         getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
668                         getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS;
669                         break;
670                     case "-f":
671                         showSourceDir = true;
672                         break;
673                     case "-i":
674                         listInstaller = true;
675                         break;
676                     case "-l":
677                         // old compat
678                         break;
679                     case "-s":
680                         listSystem = true;
681                         break;
682                     case "-U":
683                         showUid = true;
684                         break;
685                     case "-u":
686                         getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
687                         break;
688                     case "-3":
689                         listThirdParty = true;
690                         break;
691                     case "--show-versioncode":
692                         showVersionCode = true;
693                         break;
694                     case "--apex-only":
695                         getFlags |= PackageManager.MATCH_APEX;
696                         listApexOnly = true;
697                         break;
698                     case "--user":
699                         userId = UserHandle.parseUserArg(getNextArgRequired());
700                         break;
701                     case "--uid":
702                         showUid = true;
703                         uid = Integer.parseInt(getNextArgRequired());
704                         break;
705                     default:
706                         pw.println("Error: Unknown option: " + opt);
707                         return -1;
708                 }
709             }
710         } catch (RuntimeException ex) {
711             pw.println("Error: " + ex.toString());
712             return -1;
713         }
714 
715         final String filter = getNextArg();
716 
717         @SuppressWarnings("unchecked")
718         final ParceledListSlice<PackageInfo> slice =
719                 mInterface.getInstalledPackages(getFlags, userId);
720         final List<PackageInfo> packages = slice.getList();
721 
722         final int count = packages.size();
723         for (int p = 0; p < count; p++) {
724             final PackageInfo info = packages.get(p);
725             if (filter != null && !info.packageName.contains(filter)) {
726                 continue;
727             }
728             final boolean isApex = info.isApex;
729             if (uid != -1 && !isApex && info.applicationInfo.uid != uid) {
730                 continue;
731             }
732 
733             final boolean isSystem = !isApex &&
734                     (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
735             final boolean isEnabled = !isApex && info.applicationInfo.enabled;
736             if ((!listDisabled || !isEnabled) &&
737                     (!listEnabled || isEnabled) &&
738                     (!listSystem || isSystem) &&
739                     (!listThirdParty || !isSystem) &&
740                     (!listApexOnly || isApex)) {
741                 pw.print("package:");
742                 if (showSourceDir) {
743                     pw.print(info.applicationInfo.sourceDir);
744                     pw.print("=");
745                 }
746                 pw.print(info.packageName);
747                 if (showVersionCode) {
748                     pw.print(" versionCode:");
749                     if (info.applicationInfo != null) {
750                         pw.print(info.applicationInfo.longVersionCode);
751                     } else {
752                         pw.print(info.getLongVersionCode());
753                     }
754                 }
755                 if (listInstaller) {
756                     pw.print("  installer=");
757                     pw.print(mInterface.getInstallerPackageName(info.packageName));
758                 }
759                 if (showUid && !isApex) {
760                     pw.print(" uid:");
761                     pw.print(info.applicationInfo.uid);
762                 }
763                 pw.println();
764             }
765         }
766         return 0;
767     }
768 
runListPermissionGroups()769     private int runListPermissionGroups() throws RemoteException {
770         final PrintWriter pw = getOutPrintWriter();
771         final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
772 
773         final int count = pgs.size();
774         for (int p = 0; p < count ; p++) {
775             final PermissionGroupInfo pgi = pgs.get(p);
776             pw.print("permission group:");
777             pw.println(pgi.name);
778         }
779         return 0;
780     }
781 
runListPermissions()782     private int runListPermissions() throws RemoteException {
783         final PrintWriter pw = getOutPrintWriter();
784         boolean labels = false;
785         boolean groups = false;
786         boolean userOnly = false;
787         boolean summary = false;
788         boolean dangerousOnly = false;
789         String opt;
790         while ((opt = getNextOption()) != null) {
791             switch (opt) {
792                 case "-d":
793                     dangerousOnly = true;
794                     break;
795                 case "-f":
796                     labels = true;
797                     break;
798                 case "-g":
799                     groups = true;
800                     break;
801                 case "-s":
802                     groups = true;
803                     labels = true;
804                     summary = true;
805                     break;
806                 case "-u":
807                     userOnly = true;
808                     break;
809                 default:
810                     pw.println("Error: Unknown option: " + opt);
811                     return 1;
812             }
813         }
814 
815         final ArrayList<String> groupList = new ArrayList<String>();
816         if (groups) {
817             final List<PermissionGroupInfo> infos =
818                     mInterface.getAllPermissionGroups(0 /*flags*/).getList();
819             final int count = infos.size();
820             for (int i = 0; i < count; i++) {
821                 groupList.add(infos.get(i).name);
822             }
823             groupList.add(null);
824         } else {
825             final String grp = getNextArg();
826             groupList.add(grp);
827         }
828 
829         if (dangerousOnly) {
830             pw.println("Dangerous Permissions:");
831             pw.println("");
832             doListPermissions(groupList, groups, labels, summary,
833                     PermissionInfo.PROTECTION_DANGEROUS,
834                     PermissionInfo.PROTECTION_DANGEROUS);
835             if (userOnly) {
836                 pw.println("Normal Permissions:");
837                 pw.println("");
838                 doListPermissions(groupList, groups, labels, summary,
839                         PermissionInfo.PROTECTION_NORMAL,
840                         PermissionInfo.PROTECTION_NORMAL);
841             }
842         } else if (userOnly) {
843             pw.println("Dangerous and Normal Permissions:");
844             pw.println("");
845             doListPermissions(groupList, groups, labels, summary,
846                     PermissionInfo.PROTECTION_NORMAL,
847                     PermissionInfo.PROTECTION_DANGEROUS);
848         } else {
849             pw.println("All Permissions:");
850             pw.println("");
851             doListPermissions(groupList, groups, labels, summary,
852                     -10000, 10000);
853         }
854         return 0;
855     }
856 
857     private static class SessionDump {
858         boolean onlyParent; // Show parent sessions only
859         boolean onlyReady; // Show only staged sessions that are in ready state
860         boolean onlySessionId; // Show sessionId only
861     }
862 
863     // Returns true if the provided flag is a session flag and given SessionDump was updated
setSessionFlag(String flag, SessionDump sessionDump)864     private boolean setSessionFlag(String flag, SessionDump sessionDump) {
865         switch (flag) {
866             case "--only-parent":
867                 sessionDump.onlyParent = true;
868                 break;
869             case "--only-ready":
870                 sessionDump.onlyReady = true;
871                 break;
872             case "--only-sessionid":
873                 sessionDump.onlySessionId = true;
874                 break;
875             default:
876                 return false;
877         }
878         return true;
879     }
880 
runListStagedSessions()881     private int runListStagedSessions() {
882         final IndentingPrintWriter pw = new IndentingPrintWriter(
883                 getOutPrintWriter(), /* singleIndent */ "  ", /* wrapLength */ 120);
884 
885         SessionDump sessionDump = new SessionDump();
886         String opt;
887         while ((opt = getNextOption()) != null) {
888             if (!setSessionFlag(opt, sessionDump)) {
889                 pw.println("Error: Unknown option: " + opt);
890                 return -1;
891             }
892         }
893 
894         try {
895             List<SessionInfo> stagedSessions =
896                     mInterface.getPackageInstaller().getStagedSessions().getList();
897             printSessionList(pw, stagedSessions, sessionDump);
898         } catch (RemoteException e) {
899             pw.println("Failure ["
900                     + e.getClass().getName() + " - "
901                     + e.getMessage() + "]");
902             return -1;
903         }
904         return 1;
905     }
906 
printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions, SessionDump sessionDump)907     private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions,
908             SessionDump sessionDump) {
909         final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size());
910         for (SessionInfo session : stagedSessions) {
911             sessionById.put(session.getSessionId(), session);
912         }
913         for (SessionInfo session: stagedSessions) {
914             if (sessionDump.onlyReady && !session.isStagedSessionReady()) {
915                 continue;
916             }
917             if (session.getParentSessionId() != SessionInfo.INVALID_ID) {
918                 continue;
919             }
920             printSession(pw, session, sessionDump);
921             if (session.isMultiPackage() && !sessionDump.onlyParent) {
922                 pw.increaseIndent();
923                 final int[] childIds = session.getChildSessionIds();
924                 for (int i = 0; i < childIds.length; i++) {
925                     final SessionInfo childSession = sessionById.get(childIds[i]);
926                     if (childSession == null) {
927                         if (sessionDump.onlySessionId) {
928                             pw.println(childIds[i]);
929                         } else {
930                             pw.println("sessionId = " + childIds[i] + "; not found");
931                         }
932                     } else {
933                         printSession(pw, childSession, sessionDump);
934                     }
935                 }
936                 pw.decreaseIndent();
937             }
938         }
939     }
940 
printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump)941     private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) {
942         if (sessionDump.onlySessionId) {
943             pw.println(session.getSessionId());
944             return;
945         }
946         pw.println("sessionId = " + session.getSessionId()
947                 + "; appPackageName = " + session.getAppPackageName()
948                 + "; isStaged = " + session.isStaged()
949                 + "; isReady = " + session.isStagedSessionReady()
950                 + "; isApplied = " + session.isStagedSessionApplied()
951                 + "; isFailed = " + session.isStagedSessionFailed() + ";");
952     }
953 
parseIntentAndUser()954     private Intent parseIntentAndUser() throws URISyntaxException {
955         mTargetUser = UserHandle.USER_CURRENT;
956         mBrief = false;
957         mComponents = false;
958         Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
959             @Override
960             public boolean handleOption(String opt, ShellCommand cmd) {
961                 if ("--user".equals(opt)) {
962                     mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired());
963                     return true;
964                 } else if ("--brief".equals(opt)) {
965                     mBrief = true;
966                     return true;
967                 } else if ("--components".equals(opt)) {
968                     mComponents = true;
969                     return true;
970                 } else if ("--query-flags".equals(opt)) {
971                     mQueryFlags = Integer.decode(cmd.getNextArgRequired());
972                     return true;
973                 }
974                 return false;
975             }
976         });
977         mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
978                 Binder.getCallingUid(), mTargetUser, false, false, null, null);
979         return intent;
980     }
981 
printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri, boolean brief, boolean components)982     private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri,
983             boolean brief, boolean components) {
984         if (brief || components) {
985             final ComponentName comp;
986             if (ri.activityInfo != null) {
987                 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
988             } else if (ri.serviceInfo != null) {
989                 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
990             } else if (ri.providerInfo != null) {
991                 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name);
992             } else {
993                 comp = null;
994             }
995             if (comp != null) {
996                 if (!components) {
997                     pr.println(prefix + "priority=" + ri.priority
998                             + " preferredOrder=" + ri.preferredOrder
999                             + " match=0x" + Integer.toHexString(ri.match)
1000                             + " specificIndex=" + ri.specificIndex
1001                             + " isDefault=" + ri.isDefault);
1002                 }
1003                 pr.println(prefix + comp.flattenToShortString());
1004                 return;
1005             }
1006         }
1007         ri.dump(pr, prefix);
1008     }
1009 
runResolveActivity()1010     private int runResolveActivity() {
1011         Intent intent;
1012         try {
1013             intent = parseIntentAndUser();
1014         } catch (URISyntaxException e) {
1015             throw new RuntimeException(e.getMessage(), e);
1016         }
1017         try {
1018             ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
1019                     mTargetUser);
1020             PrintWriter pw = getOutPrintWriter();
1021             if (ri == null) {
1022                 pw.println("No activity found");
1023             } else {
1024                 PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1025                 printResolveInfo(pr, "", ri, mBrief, mComponents);
1026             }
1027         } catch (RemoteException e) {
1028             throw new RuntimeException("Failed calling service", e);
1029         }
1030         return 0;
1031     }
1032 
runQueryIntentActivities()1033     private int runQueryIntentActivities() {
1034         Intent intent;
1035         try {
1036             intent = parseIntentAndUser();
1037         } catch (URISyntaxException e) {
1038             throw new RuntimeException(e.getMessage(), e);
1039         }
1040         try {
1041             List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
1042                     mQueryFlags, mTargetUser).getList();
1043             PrintWriter pw = getOutPrintWriter();
1044             if (result == null || result.size() <= 0) {
1045                 pw.println("No activities found");
1046             } else {
1047                 if (!mComponents) {
1048                     pw.print(result.size()); pw.println(" activities found:");
1049                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1050                     for (int i = 0; i < result.size(); i++) {
1051                         pw.print("  Activity #"); pw.print(i); pw.println(":");
1052                         printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
1053                     }
1054                 } else {
1055                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1056                     for (int i = 0; i < result.size(); i++) {
1057                         printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1058                     }
1059                 }
1060             }
1061         } catch (RemoteException e) {
1062             throw new RuntimeException("Failed calling service", e);
1063         }
1064         return 0;
1065     }
1066 
runQueryIntentServices()1067     private int runQueryIntentServices() {
1068         Intent intent;
1069         try {
1070             intent = parseIntentAndUser();
1071         } catch (URISyntaxException e) {
1072             throw new RuntimeException(e.getMessage(), e);
1073         }
1074         try {
1075             List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
1076                     mQueryFlags, mTargetUser).getList();
1077             PrintWriter pw = getOutPrintWriter();
1078             if (result == null || result.size() <= 0) {
1079                 pw.println("No services found");
1080             } else {
1081                 if (!mComponents) {
1082                     pw.print(result.size()); pw.println(" services found:");
1083                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1084                     for (int i = 0; i < result.size(); i++) {
1085                         pw.print("  Service #"); pw.print(i); pw.println(":");
1086                         printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
1087                     }
1088                 } else {
1089                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1090                     for (int i = 0; i < result.size(); i++) {
1091                         printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1092                     }
1093                 }
1094             }
1095         } catch (RemoteException e) {
1096             throw new RuntimeException("Failed calling service", e);
1097         }
1098         return 0;
1099     }
1100 
runQueryIntentReceivers()1101     private int runQueryIntentReceivers() {
1102         Intent intent;
1103         try {
1104             intent = parseIntentAndUser();
1105         } catch (URISyntaxException e) {
1106             throw new RuntimeException(e.getMessage(), e);
1107         }
1108         try {
1109             List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
1110                     mQueryFlags, mTargetUser).getList();
1111             PrintWriter pw = getOutPrintWriter();
1112             if (result == null || result.size() <= 0) {
1113                 pw.println("No receivers found");
1114             } else {
1115                 if (!mComponents) {
1116                     pw.print(result.size()); pw.println(" receivers found:");
1117                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1118                     for (int i = 0; i < result.size(); i++) {
1119                         pw.print("  Receiver #"); pw.print(i); pw.println(":");
1120                         printResolveInfo(pr, "    ", result.get(i), mBrief, mComponents);
1121                     }
1122                 } else {
1123                     PrintWriterPrinter pr = new PrintWriterPrinter(pw);
1124                     for (int i = 0; i < result.size(); i++) {
1125                         printResolveInfo(pr, "", result.get(i), mBrief, mComponents);
1126                     }
1127                 }
1128             }
1129         } catch (RemoteException e) {
1130             throw new RuntimeException("Failed calling service", e);
1131         }
1132         return 0;
1133     }
1134 
runInstall()1135     private int runInstall() throws RemoteException {
1136         final PrintWriter pw = getOutPrintWriter();
1137         final InstallParams params = makeInstallParams();
1138         final String inPath = getNextArg();
1139 
1140         setParamsSize(params, inPath);
1141         final int sessionId = doCreateSession(params.sessionParams,
1142                 params.installerPackageName, params.userId);
1143         boolean abandonSession = true;
1144         try {
1145             if (inPath == null && params.sessionParams.sizeBytes == -1) {
1146                 pw.println("Error: must either specify a package size or an APK file");
1147                 return 1;
1148             }
1149             final boolean isApex =
1150                     (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
1151             String splitName = "base." + (isApex ? "apex" : "apk");
1152             if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName,
1153                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
1154                 return 1;
1155             }
1156             if (doCommitSession(sessionId, false /*logSuccess*/)
1157                     != PackageInstaller.STATUS_SUCCESS) {
1158                 return 1;
1159             }
1160             abandonSession = false;
1161 
1162             if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
1163                 pw.println("Success");
1164                 return 0;
1165             }
1166             return doWaitForStagedSessionRead(sessionId, params.timeoutMs, pw);
1167         } finally {
1168             if (abandonSession) {
1169                 try {
1170                     doAbandonSession(sessionId, false /*logSuccess*/);
1171                 } catch (Exception ignore) {
1172                 }
1173             }
1174         }
1175     }
1176 
doWaitForStagedSessionRead(int sessionId, long timeoutMs, PrintWriter pw)1177     private int doWaitForStagedSessionRead(int sessionId, long timeoutMs, PrintWriter pw)
1178               throws RemoteException {
1179         if (timeoutMs <= 0) {
1180             timeoutMs = DEFAULT_WAIT_MS;
1181         }
1182         PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1183                 .getSessionInfo(sessionId);
1184         if (si == null) {
1185             pw.println("Failure [Unknown session " + sessionId + "]");
1186             return 1;
1187         }
1188         if (!si.isStaged()) {
1189             pw.println("Failure [Session " + sessionId + " is not a staged session]");
1190             return 1;
1191         }
1192         long currentTime = System.currentTimeMillis();
1193         long endTime = currentTime + timeoutMs;
1194         // Using a loop instead of BroadcastReceiver since we can receive session update
1195         // broadcast only if packageInstallerName is "android". We can't always force
1196         // "android" as packageIntallerName, e.g, rollback auto implies
1197         // "-i com.android.shell".
1198         while (currentTime < endTime) {
1199             if (si != null && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
1200                 break;
1201             }
1202             SystemClock.sleep(Math.min(endTime - currentTime, 100));
1203             currentTime = System.currentTimeMillis();
1204             si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
1205         }
1206         if (si == null) {
1207             pw.println("Failure [failed to retrieve SessionInfo]");
1208             return 1;
1209         }
1210         if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
1211             pw.println("Failure [timed out after " + timeoutMs + " ms]");
1212             return 1;
1213         }
1214         if (!si.isStagedSessionReady()) {
1215             pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
1216                     + si.getStagedSessionErrorMessage() + "]");
1217             return 1;
1218         }
1219         pw.println("Success. Reboot device to apply staged session");
1220         return 0;
1221     }
1222 
runInstallAbandon()1223     private int runInstallAbandon() throws RemoteException {
1224         final int sessionId = Integer.parseInt(getNextArg());
1225         return doAbandonSession(sessionId, true /*logSuccess*/);
1226     }
1227 
runInstallCommit()1228     private int runInstallCommit() throws RemoteException {
1229         final PrintWriter pw = getOutPrintWriter();
1230         String opt;
1231         boolean waitForStagedSessionReady = true;
1232         long timeoutMs = -1;
1233         while ((opt = getNextOption()) != null) {
1234             switch (opt) {
1235                 case "--wait":
1236                     waitForStagedSessionReady = true;
1237                     // If there is only one remaining argument, then it represents the sessionId, we
1238                     // shouldn't try to parse it as timeoutMs.
1239                     if (getRemainingArgsCount() > 1) {
1240                         try {
1241                             timeoutMs = Long.parseLong(peekNextArg());
1242                             getNextArg();
1243                         } catch (NumberFormatException ignore) {
1244                         }
1245                     }
1246                     break;
1247                 case "--no-wait":
1248                     waitForStagedSessionReady = false;
1249                     break;
1250             }
1251         }
1252         final int sessionId = Integer.parseInt(getNextArg());
1253         if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
1254             return 1;
1255         }
1256         final PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
1257                 .getSessionInfo(sessionId);
1258         if (si == null || !si.isStaged() || !waitForStagedSessionReady) {
1259             pw.println("Success");
1260             return 0;
1261         }
1262         return doWaitForStagedSessionRead(sessionId, timeoutMs, pw);
1263     }
1264 
runInstallCreate()1265     private int runInstallCreate() throws RemoteException {
1266         final PrintWriter pw = getOutPrintWriter();
1267         final InstallParams installParams = makeInstallParams();
1268         final int sessionId = doCreateSession(installParams.sessionParams,
1269                 installParams.installerPackageName, installParams.userId);
1270 
1271         // NOTE: adb depends on parsing this string
1272         pw.println("Success: created install session [" + sessionId + "]");
1273         return 0;
1274     }
1275 
runInstallWrite()1276     private int runInstallWrite() throws RemoteException {
1277         long sizeBytes = -1;
1278 
1279         String opt;
1280         while ((opt = getNextOption()) != null) {
1281             if (opt.equals("-S")) {
1282                 sizeBytes = Long.parseLong(getNextArg());
1283             } else {
1284                 throw new IllegalArgumentException("Unknown option: " + opt);
1285             }
1286         }
1287 
1288         final int sessionId = Integer.parseInt(getNextArg());
1289         final String splitName = getNextArg();
1290         final String path = getNextArg();
1291         return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
1292     }
1293 
runInstallAddSession()1294     private int runInstallAddSession() throws RemoteException {
1295         final PrintWriter pw = getOutPrintWriter();
1296         final int parentSessionId = Integer.parseInt(getNextArg());
1297 
1298         List<Integer> otherSessionIds = new ArrayList<>();
1299         String opt;
1300         while ((opt = getNextArg()) != null) {
1301             otherSessionIds.add(Integer.parseInt(opt));
1302         }
1303         if (otherSessionIds.size() == 0) {
1304             pw.println("Error: At least two sessions are required.");
1305             return 1;
1306         }
1307         return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
1308                 true /*logSuccess*/);
1309     }
1310 
runInstallRemove()1311     private int runInstallRemove() throws RemoteException {
1312         final PrintWriter pw = getOutPrintWriter();
1313 
1314         final int sessionId = Integer.parseInt(getNextArg());
1315 
1316         final String splitName = getNextArg();
1317         if (splitName == null) {
1318             pw.println("Error: split name not specified");
1319             return 1;
1320         }
1321         return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
1322     }
1323 
runInstallExisting()1324     private int runInstallExisting() throws RemoteException {
1325         final PrintWriter pw = getOutPrintWriter();
1326         int userId = UserHandle.USER_SYSTEM;
1327         int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1328         String opt;
1329         boolean waitTillComplete = false;
1330         while ((opt = getNextOption()) != null) {
1331             switch (opt) {
1332                 case "--user":
1333                     userId = UserHandle.parseUserArg(getNextArgRequired());
1334                     break;
1335                 case "--ephemeral":
1336                 case "--instant":
1337                     installFlags |= PackageManager.INSTALL_INSTANT_APP;
1338                     installFlags &= ~PackageManager.INSTALL_FULL_APP;
1339                     break;
1340                 case "--full":
1341                     installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
1342                     installFlags |= PackageManager.INSTALL_FULL_APP;
1343                     break;
1344                 case "--wait":
1345                     waitTillComplete = true;
1346                     break;
1347                 case "--restrict-permissions":
1348                     installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
1349                     break;
1350                 default:
1351                     pw.println("Error: Unknown option: " + opt);
1352                     return 1;
1353             }
1354         }
1355 
1356         final String packageName = getNextArg();
1357         if (packageName == null) {
1358             pw.println("Error: package name not specified");
1359             return 1;
1360         }
1361 
1362         int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
1363         try {
1364             if (waitTillComplete) {
1365                 final LocalIntentReceiver receiver = new LocalIntentReceiver();
1366                 final IPackageInstaller installer = mInterface.getPackageInstaller();
1367                 pw.println("Installing package " + packageName + " for user: " + userId);
1368                 installer.installExistingPackage(packageName, installFlags, installReason,
1369                         receiver.getIntentSender(), userId, null);
1370                 final Intent result = receiver.getResult();
1371                 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1372                         PackageInstaller.STATUS_FAILURE);
1373                 pw.println("Received intent for package install");
1374                 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
1375             }
1376 
1377             final int res = mInterface.installExistingPackageAsUser(packageName, userId,
1378                     installFlags, installReason, null);
1379             if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
1380                 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1381             }
1382             pw.println("Package " + packageName + " installed for user: " + userId);
1383             return 0;
1384         } catch (RemoteException | NameNotFoundException e) {
1385             pw.println(e.toString());
1386             return 1;
1387         }
1388     }
1389 
runSetInstallLocation()1390     private int runSetInstallLocation() throws RemoteException {
1391         int loc;
1392 
1393         String arg = getNextArg();
1394         if (arg == null) {
1395             getErrPrintWriter().println("Error: no install location specified.");
1396             return 1;
1397         }
1398         try {
1399             loc = Integer.parseInt(arg);
1400         } catch (NumberFormatException e) {
1401             getErrPrintWriter().println("Error: install location has to be a number.");
1402             return 1;
1403         }
1404         if (!mInterface.setInstallLocation(loc)) {
1405             getErrPrintWriter().println("Error: install location has to be a number.");
1406             return 1;
1407         }
1408         return 0;
1409     }
1410 
runGetInstallLocation()1411     private int runGetInstallLocation() throws RemoteException {
1412         int loc = mInterface.getInstallLocation();
1413         String locStr = "invalid";
1414         if (loc == PackageHelper.APP_INSTALL_AUTO) {
1415             locStr = "auto";
1416         } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1417             locStr = "internal";
1418         } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1419             locStr = "external";
1420         }
1421         getOutPrintWriter().println(loc + "[" + locStr + "]");
1422         return 0;
1423     }
1424 
runMovePackage()1425     public int runMovePackage() throws RemoteException {
1426         final String packageName = getNextArg();
1427         if (packageName == null) {
1428             getErrPrintWriter().println("Error: package name not specified");
1429             return 1;
1430         }
1431         String volumeUuid = getNextArg();
1432         if ("internal".equals(volumeUuid)) {
1433             volumeUuid = null;
1434         }
1435 
1436         final int moveId = mInterface.movePackage(packageName, volumeUuid);
1437 
1438         int status = mInterface.getMoveStatus(moveId);
1439         while (!PackageManager.isMoveStatusFinished(status)) {
1440             SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1441             status = mInterface.getMoveStatus(moveId);
1442         }
1443 
1444         if (status == PackageManager.MOVE_SUCCEEDED) {
1445             getOutPrintWriter().println("Success");
1446             return 0;
1447         } else {
1448             getErrPrintWriter().println("Failure [" + status + "]");
1449             return 1;
1450         }
1451     }
1452 
runMovePrimaryStorage()1453     public int runMovePrimaryStorage() throws RemoteException {
1454         String volumeUuid = getNextArg();
1455         if ("internal".equals(volumeUuid)) {
1456             volumeUuid = null;
1457         }
1458 
1459         final int moveId = mInterface.movePrimaryStorage(volumeUuid);
1460 
1461         int status = mInterface.getMoveStatus(moveId);
1462         while (!PackageManager.isMoveStatusFinished(status)) {
1463             SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1464             status = mInterface.getMoveStatus(moveId);
1465         }
1466 
1467         if (status == PackageManager.MOVE_SUCCEEDED) {
1468             getOutPrintWriter().println("Success");
1469             return 0;
1470         } else {
1471             getErrPrintWriter().println("Failure [" + status + "]");
1472             return 1;
1473         }
1474     }
1475 
runCompile()1476     private int runCompile() throws RemoteException {
1477         final PrintWriter pw = getOutPrintWriter();
1478         boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
1479         boolean forceCompilation = false;
1480         boolean allPackages = false;
1481         boolean clearProfileData = false;
1482         String compilerFilter = null;
1483         String compilationReason = null;
1484         String checkProfilesRaw = null;
1485         boolean secondaryDex = false;
1486         String split = null;
1487         boolean compileLayouts = false;
1488 
1489         String opt;
1490         while ((opt = getNextOption()) != null) {
1491             switch (opt) {
1492                 case "-a":
1493                     allPackages = true;
1494                     break;
1495                 case "-c":
1496                     clearProfileData = true;
1497                     break;
1498                 case "-f":
1499                     forceCompilation = true;
1500                     break;
1501                 case "-m":
1502                     compilerFilter = getNextArgRequired();
1503                     break;
1504                 case "-r":
1505                     compilationReason = getNextArgRequired();
1506                     break;
1507                 case "--compile-layouts":
1508                     compileLayouts = true;
1509                     break;
1510                 case "--check-prof":
1511                     checkProfilesRaw = getNextArgRequired();
1512                     break;
1513                 case "--reset":
1514                     forceCompilation = true;
1515                     clearProfileData = true;
1516                     compilationReason = "install";
1517                     break;
1518                 case "--secondary-dex":
1519                     secondaryDex = true;
1520                     break;
1521                 case "--split":
1522                     split = getNextArgRequired();
1523                     break;
1524                 default:
1525                     pw.println("Error: Unknown option: " + opt);
1526                     return 1;
1527             }
1528         }
1529 
1530         if (checkProfilesRaw != null) {
1531             if ("true".equals(checkProfilesRaw)) {
1532                 checkProfiles = true;
1533             } else if ("false".equals(checkProfilesRaw)) {
1534                 checkProfiles = false;
1535             } else {
1536                 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
1537                 return 1;
1538             }
1539         }
1540 
1541         final boolean compilerFilterGiven = compilerFilter != null;
1542         final boolean compilationReasonGiven = compilationReason != null;
1543         // Make sure exactly one of -m, -r, or --compile-layouts is given.
1544         if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts)
1545             || (!compilerFilterGiven && compilationReasonGiven && compileLayouts)
1546             || (compilerFilterGiven && !compilationReasonGiven && compileLayouts)
1547             || (compilerFilterGiven && compilationReasonGiven && !compileLayouts)
1548             || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) {
1549             pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " +
1550                     "reason (\"-r\"), or compile layouts (\"--compile-layouts\")");
1551             return 1;
1552         }
1553 
1554         if (allPackages && split != null) {
1555             pw.println("-a cannot be specified together with --split");
1556             return 1;
1557         }
1558 
1559         if (secondaryDex && split != null) {
1560             pw.println("--secondary-dex cannot be specified together with --split");
1561             return 1;
1562         }
1563 
1564         String targetCompilerFilter = null;
1565         if (compilerFilterGiven) {
1566             if (!DexFile.isValidCompilerFilter(compilerFilter)) {
1567                 pw.println("Error: \"" + compilerFilter +
1568                         "\" is not a valid compilation filter.");
1569                 return 1;
1570             }
1571             targetCompilerFilter = compilerFilter;
1572         }
1573         if (compilationReasonGiven) {
1574             int reason = -1;
1575             for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
1576                 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
1577                         compilationReason)) {
1578                     reason = i;
1579                     break;
1580                 }
1581             }
1582             if (reason == -1) {
1583                 pw.println("Error: Unknown compilation reason: " + compilationReason);
1584                 return 1;
1585             }
1586             targetCompilerFilter =
1587                     PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
1588         }
1589 
1590 
1591         List<String> packageNames = null;
1592         if (allPackages) {
1593             packageNames = mInterface.getAllPackages();
1594         } else {
1595             String packageName = getNextArg();
1596             if (packageName == null) {
1597                 pw.println("Error: package name not specified");
1598                 return 1;
1599             }
1600             packageNames = Collections.singletonList(packageName);
1601         }
1602 
1603         List<String> failedPackages = new ArrayList<>();
1604         int index = 0;
1605         for (String packageName : packageNames) {
1606             if (clearProfileData) {
1607                 mInterface.clearApplicationProfileData(packageName);
1608             }
1609 
1610             if (allPackages) {
1611                 pw.println(++index + "/" + packageNames.size() + ": " + packageName);
1612                 pw.flush();
1613             }
1614 
1615             boolean result = true;
1616             if (compileLayouts) {
1617                 PackageManagerInternal internal = LocalServices.getService(
1618                         PackageManagerInternal.class);
1619                 result = internal.compileLayouts(packageName);
1620             } else {
1621                 result = secondaryDex
1622                     ? mInterface.performDexOptSecondary(packageName,
1623                             targetCompilerFilter, forceCompilation)
1624                     : mInterface.performDexOptMode(packageName,
1625                             checkProfiles, targetCompilerFilter, forceCompilation,
1626                             true /* bootComplete */, split);
1627             }
1628             if (!result) {
1629                 failedPackages.add(packageName);
1630             }
1631         }
1632 
1633         if (failedPackages.isEmpty()) {
1634             pw.println("Success");
1635             return 0;
1636         } else if (failedPackages.size() == 1) {
1637             pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
1638             return 1;
1639         } else {
1640             pw.print("Failure: the following packages could not be compiled: ");
1641             boolean is_first = true;
1642             for (String packageName : failedPackages) {
1643                 if (is_first) {
1644                     is_first = false;
1645                 } else {
1646                     pw.print(", ");
1647                 }
1648                 pw.print(packageName);
1649             }
1650             pw.println();
1651             return 1;
1652         }
1653     }
1654 
runreconcileSecondaryDexFiles()1655     private int runreconcileSecondaryDexFiles() throws RemoteException {
1656         String packageName = getNextArg();
1657         mInterface.reconcileSecondaryDexFiles(packageName);
1658         return 0;
1659     }
1660 
runForceDexOpt()1661     public int runForceDexOpt() throws RemoteException {
1662         mInterface.forceDexOpt(getNextArgRequired());
1663         return 0;
1664     }
1665 
runDexoptJob()1666     private int runDexoptJob() throws RemoteException {
1667         String arg;
1668         List<String> packageNames = new ArrayList<>();
1669         while ((arg = getNextArg()) != null) {
1670             packageNames.add(arg);
1671         }
1672         boolean result = mInterface.runBackgroundDexoptJob(packageNames.isEmpty() ? null :
1673                 packageNames);
1674         getOutPrintWriter().println(result ? "Success" : "Failure");
1675         return result ? 0 : -1;
1676     }
1677 
runDumpProfiles()1678     private int runDumpProfiles() throws RemoteException {
1679         String packageName = getNextArg();
1680         mInterface.dumpProfiles(packageName);
1681         return 0;
1682     }
1683 
runSnapshotProfile()1684     private int runSnapshotProfile() throws RemoteException {
1685         PrintWriter pw = getOutPrintWriter();
1686 
1687         // Parse the arguments
1688         final String packageName = getNextArg();
1689         final boolean isBootImage = "android".equals(packageName);
1690 
1691         String codePath = null;
1692         String opt;
1693         while ((opt = getNextArg()) != null) {
1694             switch (opt) {
1695                 case "--code-path":
1696                     if (isBootImage) {
1697                         pw.write("--code-path cannot be used for the boot image.");
1698                         return -1;
1699                     }
1700                     codePath = getNextArg();
1701                     break;
1702                 default:
1703                     pw.write("Unknown arg: " + opt);
1704                     return -1;
1705             }
1706         }
1707 
1708         // If no code path was explicitly requested, select the base code path.
1709         String baseCodePath = null;
1710         if (!isBootImage) {
1711             PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0,
1712                     /* userId */0);
1713             if (packageInfo == null) {
1714                 pw.write("Package not found " + packageName);
1715                 return -1;
1716             }
1717             baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
1718             if (codePath == null) {
1719                 codePath = baseCodePath;
1720             }
1721         }
1722 
1723         // Create the profile snapshot.
1724         final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
1725         // The calling package is needed to debug permission access.
1726         final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
1727                 ? "root" : "com.android.shell";
1728         final int profileType = isBootImage
1729                 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;
1730         if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
1731             pw.println("Error: Runtime profiling is not enabled");
1732             return -1;
1733         }
1734         mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName,
1735                 codePath, callback, callingPackage);
1736         if (!callback.waitTillDone()) {
1737             pw.println("Error: callback not called");
1738             return callback.mErrCode;
1739         }
1740 
1741         // Copy the snapshot profile to the output profile file.
1742         try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) {
1743             final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath)
1744                     ? "" : ("-" + new File(codePath).getName());
1745             final String outputProfilePath =
1746                     ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof";
1747             try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
1748                 Streams.copy(inStream, outStream);
1749             }
1750             // Give read permissions to the other group.
1751             Os.chmod(outputProfilePath, /*mode*/ 0644 );
1752         } catch (IOException | ErrnoException e) {
1753             pw.println("Error when reading the profile fd: " + e.getMessage());
1754             e.printStackTrace(pw);
1755             return -1;
1756         }
1757         return 0;
1758     }
1759 
1760     private static class SnapshotRuntimeProfileCallback
1761             extends ISnapshotRuntimeProfileCallback.Stub {
1762         private boolean mSuccess = false;
1763         private int mErrCode = -1;
1764         private ParcelFileDescriptor mProfileReadFd = null;
1765         private CountDownLatch mDoneSignal = new CountDownLatch(1);
1766 
1767         @Override
onSuccess(ParcelFileDescriptor profileReadFd)1768         public void onSuccess(ParcelFileDescriptor profileReadFd) {
1769             mSuccess = true;
1770             try {
1771                 // We need to dup the descriptor. We are in the same process as system server
1772                 // and we will be receiving the same object (which will be closed on the
1773                 // server side).
1774                 mProfileReadFd = profileReadFd.dup();
1775             } catch (IOException e) {
1776                 e.printStackTrace();
1777             }
1778             mDoneSignal.countDown();
1779         }
1780 
1781         @Override
onError(int errCode)1782         public void onError(int errCode) {
1783             mSuccess = false;
1784             mErrCode = errCode;
1785             mDoneSignal.countDown();
1786         }
1787 
waitTillDone()1788         boolean waitTillDone() {
1789             boolean done = false;
1790             try {
1791                 // The time-out is an arbitrary large value. Since this is a local call the result
1792                 // will come very fast.
1793                 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
1794             } catch (InterruptedException ignored) {
1795             }
1796             return done && mSuccess;
1797         }
1798     }
1799 
runUninstall()1800     private int runUninstall() throws RemoteException {
1801         final PrintWriter pw = getOutPrintWriter();
1802         int flags = 0;
1803         int userId = UserHandle.USER_ALL;
1804         long versionCode = PackageManager.VERSION_CODE_HIGHEST;
1805 
1806         String opt;
1807         while ((opt = getNextOption()) != null) {
1808             switch (opt) {
1809                 case "-k":
1810                     flags |= PackageManager.DELETE_KEEP_DATA;
1811                     break;
1812                 case "--user":
1813                     userId = UserHandle.parseUserArg(getNextArgRequired());
1814                     break;
1815                 case "--versionCode":
1816                     versionCode = Long.parseLong(getNextArgRequired());
1817                     break;
1818                 default:
1819                     pw.println("Error: Unknown option: " + opt);
1820                     return 1;
1821             }
1822         }
1823 
1824         final String packageName = getNextArg();
1825         if (packageName == null) {
1826             pw.println("Error: package name not specified");
1827             return 1;
1828         }
1829 
1830         // if a split is specified, just remove it and not the whole package
1831         final String splitName = getNextArg();
1832         if (splitName != null) {
1833             return runRemoveSplit(packageName, splitName);
1834         }
1835 
1836         userId = translateUserId(userId, true /*allowAll*/, "runUninstall");
1837         final LocalIntentReceiver receiver = new LocalIntentReceiver();
1838         PackageManagerInternal internal = LocalServices.getService(PackageManagerInternal.class);
1839 
1840         if (internal.isApexPackage(packageName)) {
1841             internal.uninstallApex(packageName, versionCode, userId, receiver.getIntentSender());
1842         } else {
1843             if (userId == UserHandle.USER_ALL) {
1844                 userId = UserHandle.USER_SYSTEM;
1845                 flags |= PackageManager.DELETE_ALL_USERS;
1846             } else {
1847                 final PackageInfo info = mInterface.getPackageInfo(packageName,
1848                         PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
1849                 if (info == null) {
1850                     pw.println("Failure [not installed for " + userId + "]");
1851                     return 1;
1852                 }
1853                 final boolean isSystem =
1854                         (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1855                 // If we are being asked to delete a system app for just one
1856                 // user set flag so it disables rather than reverting to system
1857                 // version of the app.
1858                 if (isSystem) {
1859                     flags |= PackageManager.DELETE_SYSTEM_APP;
1860                 }
1861             }
1862 
1863             mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
1864                             versionCode), null /*callerPackageName*/, flags,
1865                     receiver.getIntentSender(), userId);
1866         }
1867 
1868         final Intent result = receiver.getResult();
1869         final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1870                 PackageInstaller.STATUS_FAILURE);
1871         if (status == PackageInstaller.STATUS_SUCCESS) {
1872             pw.println("Success");
1873             return 0;
1874         } else {
1875             pw.println("Failure ["
1876                     + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1877             return 1;
1878         }
1879     }
1880 
runRemoveSplit(String packageName, String splitName)1881     private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
1882         final PrintWriter pw = getOutPrintWriter();
1883         final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1884         sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1885         sessionParams.appPackageName = packageName;
1886         final int sessionId =
1887                 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
1888         boolean abandonSession = true;
1889         try {
1890             if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
1891                     != PackageInstaller.STATUS_SUCCESS) {
1892                 return 1;
1893             }
1894             if (doCommitSession(sessionId, false /*logSuccess*/)
1895                     != PackageInstaller.STATUS_SUCCESS) {
1896                 return 1;
1897             }
1898             abandonSession = false;
1899             pw.println("Success");
1900             return 0;
1901         } finally {
1902             if (abandonSession) {
1903                 try {
1904                     doAbandonSession(sessionId, false /*logSuccess*/);
1905                 } catch (Exception ignore) {
1906                 }
1907             }
1908         }
1909     }
1910 
1911     static class ClearDataObserver extends IPackageDataObserver.Stub {
1912         boolean finished;
1913         boolean result;
1914 
1915         @Override
onRemoveCompleted(String packageName, boolean succeeded)1916         public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1917             synchronized (this) {
1918                 finished = true;
1919                 result = succeeded;
1920                 notifyAll();
1921             }
1922         }
1923     }
1924 
runClear()1925     private int runClear() throws RemoteException {
1926         int userId = UserHandle.USER_SYSTEM;
1927         String option = getNextOption();
1928         if (option != null && option.equals("--user")) {
1929             userId = UserHandle.parseUserArg(getNextArgRequired());
1930         }
1931 
1932         String pkg = getNextArg();
1933         if (pkg == null) {
1934             getErrPrintWriter().println("Error: no package specified");
1935             return 1;
1936         }
1937 
1938         ClearDataObserver obs = new ClearDataObserver();
1939         ActivityManager.getService().clearApplicationUserData(pkg, false, obs, userId);
1940         synchronized (obs) {
1941             while (!obs.finished) {
1942                 try {
1943                     obs.wait();
1944                 } catch (InterruptedException e) {
1945                 }
1946             }
1947         }
1948 
1949         if (obs.result) {
1950             getOutPrintWriter().println("Success");
1951             return 0;
1952         } else {
1953             getErrPrintWriter().println("Failed");
1954             return 1;
1955         }
1956     }
1957 
enabledSettingToString(int state)1958     private static String enabledSettingToString(int state) {
1959         switch (state) {
1960             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1961                 return "default";
1962             case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1963                 return "enabled";
1964             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1965                 return "disabled";
1966             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1967                 return "disabled-user";
1968             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1969                 return "disabled-until-used";
1970         }
1971         return "unknown";
1972     }
1973 
runSetEnabledSetting(int state)1974     private int runSetEnabledSetting(int state) throws RemoteException {
1975         int userId = UserHandle.USER_SYSTEM;
1976         String option = getNextOption();
1977         if (option != null && option.equals("--user")) {
1978             userId = UserHandle.parseUserArg(getNextArgRequired());
1979         }
1980 
1981         String pkg = getNextArg();
1982         if (pkg == null) {
1983             getErrPrintWriter().println("Error: no package or component specified");
1984             return 1;
1985         }
1986         ComponentName cn = ComponentName.unflattenFromString(pkg);
1987         if (cn == null) {
1988             mInterface.setApplicationEnabledSetting(pkg, state, 0, userId,
1989                     "shell:" + android.os.Process.myUid());
1990             getOutPrintWriter().println("Package " + pkg + " new state: "
1991                     + enabledSettingToString(
1992                     mInterface.getApplicationEnabledSetting(pkg, userId)));
1993             return 0;
1994         } else {
1995             mInterface.setComponentEnabledSetting(cn, state, 0, userId);
1996             getOutPrintWriter().println("Component " + cn.toShortString() + " new state: "
1997                     + enabledSettingToString(
1998                     mInterface.getComponentEnabledSetting(cn, userId)));
1999             return 0;
2000         }
2001     }
2002 
runSetHiddenSetting(boolean state)2003     private int runSetHiddenSetting(boolean state) throws RemoteException {
2004         int userId = UserHandle.USER_SYSTEM;
2005         String option = getNextOption();
2006         if (option != null && option.equals("--user")) {
2007             userId = UserHandle.parseUserArg(getNextArgRequired());
2008         }
2009 
2010         String pkg = getNextArg();
2011         if (pkg == null) {
2012             getErrPrintWriter().println("Error: no package or component specified");
2013             return 1;
2014         }
2015         mInterface.setApplicationHiddenSettingAsUser(pkg, state, userId);
2016         getOutPrintWriter().println("Package " + pkg + " new hidden state: "
2017                 + mInterface.getApplicationHiddenSettingAsUser(pkg, userId));
2018         return 0;
2019     }
2020 
runSuspend(boolean suspendedState)2021     private int runSuspend(boolean suspendedState) {
2022         final PrintWriter pw = getOutPrintWriter();
2023         int userId = UserHandle.USER_SYSTEM;
2024         String dialogMessage = null;
2025         final PersistableBundle appExtras = new PersistableBundle();
2026         final PersistableBundle launcherExtras = new PersistableBundle();
2027         String opt;
2028         while ((opt = getNextOption()) != null) {
2029             switch (opt) {
2030                 case "--user":
2031                     userId = UserHandle.parseUserArg(getNextArgRequired());
2032                     break;
2033                 case "--dialogMessage":
2034                     dialogMessage = getNextArgRequired();
2035                     break;
2036                 case "--ael":
2037                 case "--aes":
2038                 case "--aed":
2039                 case "--lel":
2040                 case "--les":
2041                 case "--led":
2042                     final String key = getNextArgRequired();
2043                     final String val = getNextArgRequired();
2044                     if (!suspendedState) {
2045                         break;
2046                     }
2047                     final PersistableBundle bundleToInsert =
2048                             opt.startsWith("--a") ? appExtras : launcherExtras;
2049                     switch (opt.charAt(4)) {
2050                         case 'l':
2051                             bundleToInsert.putLong(key, Long.valueOf(val));
2052                             break;
2053                         case 'd':
2054                             bundleToInsert.putDouble(key, Double.valueOf(val));
2055                             break;
2056                         case 's':
2057                             bundleToInsert.putString(key, val);
2058                             break;
2059                     }
2060                     break;
2061                 default:
2062                     pw.println("Error: Unknown option: " + opt);
2063                     return 1;
2064             }
2065         }
2066 
2067         final String packageName = getNextArg();
2068         if (packageName == null) {
2069             pw.println("Error: package name not specified");
2070             return 1;
2071         }
2072         final String callingPackage =
2073                 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
2074 
2075         final SuspendDialogInfo info;
2076         if (!TextUtils.isEmpty(dialogMessage)) {
2077             info = new SuspendDialogInfo.Builder()
2078                     .setMessage(dialogMessage)
2079                     .build();
2080         } else {
2081             info = null;
2082         }
2083         try {
2084             mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
2085                     appExtras, launcherExtras, info, callingPackage, userId);
2086             pw.println("Package " + packageName + " new suspended state: "
2087                     + mInterface.isPackageSuspendedForUser(packageName, userId));
2088             return 0;
2089         } catch (RemoteException | IllegalArgumentException e) {
2090             pw.println(e.toString());
2091             return 1;
2092         }
2093     }
2094 
runGrantRevokePermission(boolean grant)2095     private int runGrantRevokePermission(boolean grant) throws RemoteException {
2096         int userId = UserHandle.USER_SYSTEM;
2097 
2098         String opt = null;
2099         while ((opt = getNextOption()) != null) {
2100             if (opt.equals("--user")) {
2101                 userId = UserHandle.parseUserArg(getNextArgRequired());
2102             }
2103         }
2104 
2105         String pkg = getNextArg();
2106         if (pkg == null) {
2107             getErrPrintWriter().println("Error: no package specified");
2108             return 1;
2109         }
2110         String perm = getNextArg();
2111         if (perm == null) {
2112             getErrPrintWriter().println("Error: no permission specified");
2113             return 1;
2114         }
2115 
2116         if (grant) {
2117             mInterface.grantRuntimePermission(pkg, perm, userId);
2118         } else {
2119             mInterface.revokeRuntimePermission(pkg, perm, userId);
2120         }
2121         return 0;
2122     }
2123 
runResetPermissions()2124     private int runResetPermissions() throws RemoteException {
2125         mInterface.resetRuntimePermissions();
2126         return 0;
2127     }
2128 
runSetPermissionEnforced()2129     private int runSetPermissionEnforced() throws RemoteException {
2130         final String permission = getNextArg();
2131         if (permission == null) {
2132             getErrPrintWriter().println("Error: no permission specified");
2133             return 1;
2134         }
2135         final String enforcedRaw = getNextArg();
2136         if (enforcedRaw == null) {
2137             getErrPrintWriter().println("Error: no enforcement specified");
2138             return 1;
2139         }
2140         mInterface.setPermissionEnforced(permission, Boolean.parseBoolean(enforcedRaw));
2141         return 0;
2142     }
2143 
isVendorApp(String pkg)2144     private boolean isVendorApp(String pkg) {
2145         try {
2146             final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2147             return info != null && info.applicationInfo.isVendor();
2148         } catch (RemoteException e) {
2149             return false;
2150         }
2151     }
2152 
isProductApp(String pkg)2153     private boolean isProductApp(String pkg) {
2154         try {
2155             final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2156             return info != null && info.applicationInfo.isProduct();
2157         } catch (RemoteException e) {
2158             return false;
2159         }
2160     }
2161 
isSystemExtApp(String pkg)2162     private boolean isSystemExtApp(String pkg) {
2163         try {
2164             final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
2165             return info != null && info.applicationInfo.isSystemExt();
2166         } catch (RemoteException e) {
2167             return false;
2168         }
2169     }
2170 
runGetPrivappPermissions()2171     private int runGetPrivappPermissions() {
2172         final String pkg = getNextArg();
2173         if (pkg == null) {
2174             getErrPrintWriter().println("Error: no package specified.");
2175             return 1;
2176         }
2177 
2178         ArraySet<String> privAppPermissions = null;
2179         if (isVendorApp(pkg)) {
2180             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
2181         } else if (isProductApp(pkg)) {
2182             privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
2183         } else if (isSystemExtApp(pkg)) {
2184             privAppPermissions = SystemConfig.getInstance()
2185                     .getSystemExtPrivAppPermissions(pkg);
2186         } else {
2187             privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
2188         }
2189 
2190         getOutPrintWriter().println(privAppPermissions == null
2191                 ? "{}" : privAppPermissions.toString());
2192         return 0;
2193     }
2194 
runGetPrivappDenyPermissions()2195     private int runGetPrivappDenyPermissions() {
2196         final String pkg = getNextArg();
2197         if (pkg == null) {
2198             getErrPrintWriter().println("Error: no package specified.");
2199             return 1;
2200         }
2201 
2202         ArraySet<String> privAppPermissions = null;
2203         if (isVendorApp(pkg)) {
2204             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
2205         } else if (isProductApp(pkg)) {
2206             privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
2207         } else if (isSystemExtApp(pkg)) {
2208             privAppPermissions = SystemConfig.getInstance()
2209                     .getSystemExtPrivAppDenyPermissions(pkg);
2210         } else {
2211             privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
2212         }
2213 
2214         getOutPrintWriter().println(privAppPermissions == null
2215                 ? "{}" : privAppPermissions.toString());
2216         return 0;
2217     }
2218 
runGetOemPermissions()2219     private int runGetOemPermissions() {
2220         final String pkg = getNextArg();
2221         if (pkg == null) {
2222             getErrPrintWriter().println("Error: no package specified.");
2223             return 1;
2224         }
2225         final Map<String, Boolean> oemPermissions = SystemConfig.getInstance()
2226                 .getOemPermissions(pkg);
2227         if (oemPermissions == null || oemPermissions.isEmpty()) {
2228             getOutPrintWriter().println("{}");
2229         } else {
2230             oemPermissions.forEach((permission, granted) ->
2231                     getOutPrintWriter().println(permission + " granted:" + granted)
2232             );
2233         }
2234         return 0;
2235     }
2236 
linkStateToString(int state)2237     private String linkStateToString(int state) {
2238         switch (state) {
2239             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
2240             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
2241             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
2242             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
2243             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
2244         }
2245         return "Unknown link state: " + state;
2246     }
2247 
2248     // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
runSetAppLink()2249     private int runSetAppLink() throws RemoteException {
2250         int userId = UserHandle.USER_SYSTEM;
2251 
2252         String opt;
2253         while ((opt = getNextOption()) != null) {
2254             if (opt.equals("--user")) {
2255                 userId = UserHandle.parseUserArg(getNextArgRequired());
2256             } else {
2257                 getErrPrintWriter().println("Error: unknown option: " + opt);
2258                 return 1;
2259             }
2260         }
2261 
2262         // Package name to act on; required
2263         final String pkg = getNextArg();
2264         if (pkg == null) {
2265             getErrPrintWriter().println("Error: no package specified.");
2266             return 1;
2267         }
2268 
2269         // State to apply; {always|ask|never|undefined}, required
2270         final String modeString = getNextArg();
2271         if (modeString == null) {
2272             getErrPrintWriter().println("Error: no app link state specified.");
2273             return 1;
2274         }
2275 
2276         final int newMode;
2277         switch (modeString.toLowerCase()) {
2278             case "undefined":
2279                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
2280                 break;
2281 
2282             case "always":
2283                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
2284                 break;
2285 
2286             case "ask":
2287                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
2288                 break;
2289 
2290             case "always-ask":
2291                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
2292                 break;
2293 
2294             case "never":
2295                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
2296                 break;
2297 
2298             default:
2299                 getErrPrintWriter().println("Error: unknown app link state '" + modeString + "'");
2300                 return 1;
2301         }
2302 
2303         final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
2304         if (info == null) {
2305             getErrPrintWriter().println("Error: package " + pkg + " not found.");
2306             return 1;
2307         }
2308 
2309         if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2310             getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2311             return 1;
2312         }
2313 
2314         if (!mInterface.updateIntentVerificationStatus(pkg, newMode, userId)) {
2315             getErrPrintWriter().println("Error: unable to update app link status for " + pkg);
2316             return 1;
2317         }
2318 
2319         return 0;
2320     }
2321 
2322     // pm get-app-link [--user USER_ID] PACKAGE
runGetAppLink()2323     private int runGetAppLink() throws RemoteException {
2324         int userId = UserHandle.USER_SYSTEM;
2325 
2326         String opt;
2327         while ((opt = getNextOption()) != null) {
2328             if (opt.equals("--user")) {
2329                 userId = UserHandle.parseUserArg(getNextArgRequired());
2330             } else {
2331                 getErrPrintWriter().println("Error: unknown option: " + opt);
2332                 return 1;
2333             }
2334         }
2335 
2336         // Package name to act on; required
2337         final String pkg = getNextArg();
2338         if (pkg == null) {
2339             getErrPrintWriter().println("Error: no package specified.");
2340             return 1;
2341         }
2342 
2343         final PackageInfo info = mInterface.getPackageInfo(pkg, 0, userId);
2344         if (info == null) {
2345             getErrPrintWriter().println("Error: package " + pkg + " not found.");
2346             return 1;
2347         }
2348 
2349         if ((info.applicationInfo.privateFlags
2350                 & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
2351             getErrPrintWriter().println("Error: package " + pkg + " does not handle web links.");
2352             return 1;
2353         }
2354 
2355         getOutPrintWriter().println(linkStateToString(
2356                 mInterface.getIntentVerificationStatus(pkg, userId)));
2357 
2358         return 0;
2359     }
2360 
runTrimCaches()2361     private int runTrimCaches() throws RemoteException {
2362         String size = getNextArg();
2363         if (size == null) {
2364             getErrPrintWriter().println("Error: no size specified");
2365             return 1;
2366         }
2367         long multiplier = 1;
2368         int len = size.length();
2369         char c = size.charAt(len - 1);
2370         if (c < '0' || c > '9') {
2371             if (c == 'K' || c == 'k') {
2372                 multiplier = 1024L;
2373             } else if (c == 'M' || c == 'm') {
2374                 multiplier = 1024L*1024L;
2375             } else if (c == 'G' || c == 'g') {
2376                 multiplier = 1024L*1024L*1024L;
2377             } else {
2378                 getErrPrintWriter().println("Invalid suffix: " + c);
2379                 return 1;
2380             }
2381             size = size.substring(0, len-1);
2382         }
2383         long sizeVal;
2384         try {
2385             sizeVal = Long.parseLong(size) * multiplier;
2386         } catch (NumberFormatException e) {
2387             getErrPrintWriter().println("Error: expected number at: " + size);
2388             return 1;
2389         }
2390         String volumeUuid = getNextArg();
2391         if ("internal".equals(volumeUuid)) {
2392             volumeUuid = null;
2393         }
2394         ClearDataObserver obs = new ClearDataObserver();
2395         mInterface.freeStorageAndNotify(volumeUuid, sizeVal,
2396                 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs);
2397         synchronized (obs) {
2398             while (!obs.finished) {
2399                 try {
2400                     obs.wait();
2401                 } catch (InterruptedException e) {
2402                 }
2403             }
2404         }
2405         return 0;
2406     }
2407 
isNumber(String s)2408     private static boolean isNumber(String s) {
2409         try {
2410             Integer.parseInt(s);
2411         } catch (NumberFormatException nfe) {
2412             return false;
2413         }
2414         return true;
2415     }
2416 
runCreateUser()2417     public int runCreateUser() throws RemoteException {
2418         String name;
2419         int userId = -1;
2420         int flags = 0;
2421         String opt;
2422         boolean preCreateOnly = false;
2423         while ((opt = getNextOption()) != null) {
2424             if ("--profileOf".equals(opt)) {
2425                 userId = UserHandle.parseUserArg(getNextArgRequired());
2426             } else if ("--managed".equals(opt)) {
2427                 flags |= UserInfo.FLAG_MANAGED_PROFILE;
2428             } else if ("--restricted".equals(opt)) {
2429                 flags |= UserInfo.FLAG_RESTRICTED;
2430             } else if ("--ephemeral".equals(opt)) {
2431                 flags |= UserInfo.FLAG_EPHEMERAL;
2432             } else if ("--guest".equals(opt)) {
2433                 flags |= UserInfo.FLAG_GUEST;
2434             } else if ("--demo".equals(opt)) {
2435                 flags |= UserInfo.FLAG_DEMO;
2436             } else if ("--pre-create-only".equals(opt)) {
2437                 preCreateOnly = true;
2438             } else {
2439                 getErrPrintWriter().println("Error: unknown option " + opt);
2440                 return 1;
2441             }
2442         }
2443         String arg = getNextArg();
2444         if (arg == null && !preCreateOnly) {
2445             getErrPrintWriter().println("Error: no user name specified.");
2446             return 1;
2447         }
2448         if (arg != null && preCreateOnly) {
2449             getErrPrintWriter().println("Warning: name is ignored for pre-created users");
2450         }
2451 
2452         name = arg;
2453         UserInfo info;
2454         IUserManager um = IUserManager.Stub.asInterface(
2455                 ServiceManager.getService(Context.USER_SERVICE));
2456         IAccountManager accm = IAccountManager.Stub.asInterface(
2457                 ServiceManager.getService(Context.ACCOUNT_SERVICE));
2458         if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
2459             // In non-split user mode, userId can only be SYSTEM
2460             int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
2461             info = um.createRestrictedProfile(name, parentUserId);
2462             accm.addSharedAccountsFromParentUser(parentUserId, userId,
2463                     (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
2464         } else if (userId < 0) {
2465             info = preCreateOnly ? um.preCreateUser(flags) : um.createUser(name, flags);
2466         } else {
2467             info = um.createProfileForUser(name, flags, userId, null);
2468         }
2469 
2470         if (info != null) {
2471             getOutPrintWriter().println("Success: created user id " + info.id);
2472             return 0;
2473         } else {
2474             getErrPrintWriter().println("Error: couldn't create User.");
2475             return 1;
2476         }
2477     }
2478 
runRemoveUser()2479     public int runRemoveUser() throws RemoteException {
2480         int userId;
2481         String arg = getNextArg();
2482         if (arg == null) {
2483             getErrPrintWriter().println("Error: no user id specified.");
2484             return 1;
2485         }
2486         userId = UserHandle.parseUserArg(arg);
2487         IUserManager um = IUserManager.Stub.asInterface(
2488                 ServiceManager.getService(Context.USER_SERVICE));
2489         if (um.removeUser(userId)) {
2490             getOutPrintWriter().println("Success: removed user");
2491             return 0;
2492         } else {
2493             getErrPrintWriter().println("Error: couldn't remove user id " + userId);
2494             return 1;
2495         }
2496     }
2497 
runSetUserRestriction()2498     public int runSetUserRestriction() throws RemoteException {
2499         int userId = UserHandle.USER_SYSTEM;
2500         String opt = getNextOption();
2501         if (opt != null && "--user".equals(opt)) {
2502             userId = UserHandle.parseUserArg(getNextArgRequired());
2503         }
2504 
2505         String restriction = getNextArg();
2506         String arg = getNextArg();
2507         boolean value;
2508         if ("1".equals(arg)) {
2509             value = true;
2510         } else if ("0".equals(arg)) {
2511             value = false;
2512         } else {
2513             getErrPrintWriter().println("Error: valid value not specified");
2514             return 1;
2515         }
2516         IUserManager um = IUserManager.Stub.asInterface(
2517                 ServiceManager.getService(Context.USER_SERVICE));
2518         um.setUserRestriction(restriction, value, userId);
2519         return 0;
2520     }
2521 
runGetMaxUsers()2522     public int runGetMaxUsers() {
2523         getOutPrintWriter().println("Maximum supported users: "
2524                 + UserManager.getMaxSupportedUsers());
2525         return 0;
2526     }
2527 
runGetMaxRunningUsers()2528     public int runGetMaxRunningUsers() {
2529         ActivityManagerInternal activityManagerInternal =
2530                 LocalServices.getService(ActivityManagerInternal.class);
2531         getOutPrintWriter().println("Maximum supported running users: "
2532                 + activityManagerInternal.getMaxRunningUsers());
2533         return 0;
2534     }
2535 
2536     private static class InstallParams {
2537         SessionParams sessionParams;
2538         String installerPackageName;
2539         int userId = UserHandle.USER_ALL;
2540         boolean mWaitForStagedSessionReady = true;
2541         long timeoutMs = DEFAULT_WAIT_MS;
2542     }
2543 
makeInstallParams()2544     private InstallParams makeInstallParams() {
2545         final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2546         final InstallParams params = new InstallParams();
2547 
2548         params.sessionParams = sessionParams;
2549         // Whitelist all permissions by default
2550         sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2551 
2552         String opt;
2553         boolean replaceExisting = true;
2554         while ((opt = getNextOption()) != null) {
2555             switch (opt) {
2556                 case "-r": // ignore
2557                     break;
2558                 case "-R":
2559                     replaceExisting = false;
2560                     break;
2561                 case "-i":
2562                     params.installerPackageName = getNextArg();
2563                     if (params.installerPackageName == null) {
2564                         throw new IllegalArgumentException("Missing installer package");
2565                     }
2566                     break;
2567                 case "-t":
2568                     sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
2569                     break;
2570                 case "-f":
2571                     sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
2572                     break;
2573                 case "-d":
2574                     sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
2575                     break;
2576                 case "-g":
2577                     sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
2578                     break;
2579                 case "--restrict-permissions":
2580                     sessionParams.installFlags &=
2581                             ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
2582                     break;
2583                 case "--dont-kill":
2584                     sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
2585                     break;
2586                 case "--originating-uri":
2587                     sessionParams.originatingUri = Uri.parse(getNextArg());
2588                     break;
2589                 case "--referrer":
2590                     sessionParams.referrerUri = Uri.parse(getNextArg());
2591                     break;
2592                 case "-p":
2593                     sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;
2594                     sessionParams.appPackageName = getNextArg();
2595                     if (sessionParams.appPackageName == null) {
2596                         throw new IllegalArgumentException("Missing inherit package name");
2597                     }
2598                     break;
2599                 case "--pkg":
2600                     sessionParams.appPackageName = getNextArg();
2601                     if (sessionParams.appPackageName == null) {
2602                         throw new IllegalArgumentException("Missing package name");
2603                     }
2604                     break;
2605                 case "-S":
2606                     final long sizeBytes = Long.parseLong(getNextArg());
2607                     if (sizeBytes <= 0) {
2608                         throw new IllegalArgumentException("Size must be positive");
2609                     }
2610                     sessionParams.setSize(sizeBytes);
2611                     break;
2612                 case "--abi":
2613                     sessionParams.abiOverride = checkAbiArgument(getNextArg());
2614                     break;
2615                 case "--ephemeral":
2616                 case "--instant":
2617                 case "--instantapp":
2618                     sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
2619                     break;
2620                 case "--full":
2621                     sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
2622                     break;
2623                 case "--preload":
2624                     sessionParams.setInstallAsVirtualPreload();
2625                     break;
2626                 case "--user":
2627                     params.userId = UserHandle.parseUserArg(getNextArgRequired());
2628                     break;
2629                 case "--install-location":
2630                     sessionParams.installLocation = Integer.parseInt(getNextArg());
2631                     break;
2632                 case "--install-reason":
2633                     sessionParams.installReason = Integer.parseInt(getNextArg());
2634                     break;
2635                 case "--force-uuid":
2636                     sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
2637                     sessionParams.volumeUuid = getNextArg();
2638                     if ("internal".equals(sessionParams.volumeUuid)) {
2639                         sessionParams.volumeUuid = null;
2640                     }
2641                     break;
2642                 case "--force-sdk": // ignore
2643                     break;
2644                 case "--apex":
2645                     sessionParams.setInstallAsApex();
2646                     sessionParams.setStaged();
2647                     break;
2648                 case "--multi-package":
2649                     sessionParams.setMultiPackage();
2650                     break;
2651                 case "--staged":
2652                     sessionParams.setStaged();
2653                     break;
2654                 case "--force-queryable":
2655                     break;
2656                 case "--enable-rollback":
2657                     if (params.installerPackageName == null) {
2658                         // com.android.shell has the TEST_MANAGE_ROLLBACKS
2659                         // permission needed to enable rollback for non-module
2660                         // packages, which is likely what the user wants when
2661                         // enabling rollback through the shell command. Set
2662                         // the installer to com.android.shell if no installer
2663                         // has been provided so that the user doesn't have to
2664                         // remember to set it themselves.
2665                         params.installerPackageName = "com.android.shell";
2666                     }
2667                     sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
2668                     break;
2669                 case "--wait":
2670                     params.mWaitForStagedSessionReady = true;
2671                     try {
2672                         params.timeoutMs = Long.parseLong(peekNextArg());
2673                         getNextArg();
2674                     } catch (NumberFormatException ignore) {
2675                     }
2676                     break;
2677                 case "--no-wait":
2678                     params.mWaitForStagedSessionReady = false;
2679                     break;
2680                 default:
2681                     throw new IllegalArgumentException("Unknown option " + opt);
2682             }
2683         }
2684         if (replaceExisting) {
2685             sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
2686         }
2687         return params;
2688     }
2689 
runSetHomeActivity()2690     private int runSetHomeActivity() {
2691         final PrintWriter pw = getOutPrintWriter();
2692         int userId = UserHandle.USER_SYSTEM;
2693         String opt;
2694         while ((opt = getNextOption()) != null) {
2695             switch (opt) {
2696                 case "--user":
2697                     userId = UserHandle.parseUserArg(getNextArgRequired());
2698                     break;
2699                 default:
2700                     pw.println("Error: Unknown option: " + opt);
2701                     return 1;
2702             }
2703         }
2704 
2705         String pkgName;
2706         String component = getNextArg();
2707         if (component.indexOf('/') < 0) {
2708             // No component specified, so assume it's just a package name.
2709             pkgName = component;
2710         } else {
2711             ComponentName componentName =
2712                     component != null ? ComponentName.unflattenFromString(component) : null;
2713             if (componentName == null) {
2714                 pw.println("Error: invalid component name");
2715                 return 1;
2716             }
2717             pkgName = componentName.getPackageName();
2718         }
2719 
2720 
2721         final CompletableFuture<Boolean> future = new CompletableFuture<>();
2722         final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
2723         try {
2724             IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
2725                     ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
2726             roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
2727                     0, userId, callback);
2728             boolean success = future.get();
2729             if (success) {
2730                 pw.println("Success");
2731                 return 0;
2732             } else {
2733                 pw.println("Error: Failed to set default home.");
2734                 return 1;
2735             }
2736         } catch (Exception e) {
2737             pw.println(e.toString());
2738             return 1;
2739         }
2740     }
2741 
runSetInstaller()2742     private int runSetInstaller() throws RemoteException {
2743         final String targetPackage = getNextArg();
2744         final String installerPackageName = getNextArg();
2745 
2746         if (targetPackage == null || installerPackageName == null) {
2747             getErrPrintWriter().println("Must provide both target and installer package names");
2748             return 1;
2749         }
2750 
2751         mInterface.setInstallerPackageName(targetPackage, installerPackageName);
2752         getOutPrintWriter().println("Success");
2753         return 0;
2754     }
2755 
runGetInstantAppResolver()2756     private int runGetInstantAppResolver() {
2757         final PrintWriter pw = getOutPrintWriter();
2758         try {
2759             final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
2760             if (instantAppsResolver == null) {
2761                 return 1;
2762             }
2763             pw.println(instantAppsResolver.flattenToString());
2764             return 0;
2765         } catch (Exception e) {
2766             pw.println(e.toString());
2767             return 1;
2768         }
2769     }
2770 
runHasFeature()2771     private int runHasFeature() {
2772         final PrintWriter err = getErrPrintWriter();
2773         final String featureName = getNextArg();
2774         if (featureName == null) {
2775             err.println("Error: expected FEATURE name");
2776             return 1;
2777         }
2778         final String versionString = getNextArg();
2779         try {
2780             final int version = (versionString == null) ? 0 : Integer.parseInt(versionString);
2781             final boolean hasFeature = mInterface.hasSystemFeature(featureName, version);
2782             getOutPrintWriter().println(hasFeature);
2783             return hasFeature ? 0 : 1;
2784         } catch (NumberFormatException e) {
2785             err.println("Error: illegal version number " + versionString);
2786             return 1;
2787         } catch (RemoteException e) {
2788             err.println(e.toString());
2789             return 1;
2790         }
2791     }
2792 
runDump()2793     private int runDump() {
2794         String pkg = getNextArg();
2795         if (pkg == null) {
2796             getErrPrintWriter().println("Error: no package specified");
2797             return 1;
2798         }
2799         ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg);
2800         return 0;
2801     }
2802 
runSetHarmfulAppWarning()2803     private int runSetHarmfulAppWarning() throws RemoteException {
2804         int userId = UserHandle.USER_CURRENT;
2805 
2806         String opt;
2807         while ((opt = getNextOption()) != null) {
2808             if (opt.equals("--user")) {
2809                 userId = UserHandle.parseUserArg(getNextArgRequired());
2810             } else {
2811                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2812                 return -1;
2813             }
2814         }
2815 
2816         userId = translateUserId(userId, false /*allowAll*/, "runSetHarmfulAppWarning");
2817 
2818         final String packageName = getNextArgRequired();
2819         final String warning = getNextArg();
2820 
2821         mInterface.setHarmfulAppWarning(packageName, warning, userId);
2822 
2823         return 0;
2824     }
2825 
runGetHarmfulAppWarning()2826     private int runGetHarmfulAppWarning() throws RemoteException {
2827         int userId = UserHandle.USER_CURRENT;
2828 
2829         String opt;
2830         while ((opt = getNextOption()) != null) {
2831             if (opt.equals("--user")) {
2832                 userId = UserHandle.parseUserArg(getNextArgRequired());
2833             } else {
2834                 getErrPrintWriter().println("Error: Unknown option: " + opt);
2835                 return -1;
2836             }
2837         }
2838 
2839         userId = translateUserId(userId, false /*allowAll*/, "runGetHarmfulAppWarning");
2840 
2841         final String packageName = getNextArgRequired();
2842         final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, userId);
2843         if (!TextUtils.isEmpty(warning)) {
2844             getOutPrintWriter().println(warning);
2845             return 0;
2846         } else {
2847             return 1;
2848         }
2849     }
2850 
checkAbiArgument(String abi)2851     private static String checkAbiArgument(String abi) {
2852         if (TextUtils.isEmpty(abi)) {
2853             throw new IllegalArgumentException("Missing ABI argument");
2854         }
2855 
2856         if ("-".equals(abi)) {
2857             return abi;
2858         }
2859 
2860         final String[] supportedAbis = Build.SUPPORTED_ABIS;
2861         for (String supportedAbi : supportedAbis) {
2862             if (supportedAbi.equals(abi)) {
2863                 return abi;
2864             }
2865         }
2866 
2867         throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
2868     }
2869 
translateUserId(int userId, boolean allowAll, String logContext)2870     private int translateUserId(int userId, boolean allowAll, String logContext) {
2871         return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2872                 userId, allowAll, true, logContext, "pm command");
2873     }
2874 
doCreateSession(SessionParams params, String installerPackageName, int userId)2875     private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2876             throws RemoteException {
2877         userId = translateUserId(userId, true /*allowAll*/, "runInstallCreate");
2878         if (userId == UserHandle.USER_ALL) {
2879             userId = UserHandle.USER_SYSTEM;
2880             params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2881         }
2882 
2883         final int sessionId = mInterface.getPackageInstaller()
2884                 .createSession(params, installerPackageName, userId);
2885         return sessionId;
2886     }
2887 
doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess)2888     private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
2889             boolean logSuccess) throws RemoteException {
2890         PackageInstaller.Session session = null;
2891         try {
2892             final PrintWriter pw = getOutPrintWriter();
2893             final ParcelFileDescriptor fd;
2894             if (STDIN_PATH.equals(inPath)) {
2895                 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
2896             } else if (inPath != null) {
2897                 fd = openFileForSystem(inPath, "r");
2898                 if (fd == null) {
2899                     return -1;
2900                 }
2901                 sizeBytes = fd.getStatSize();
2902                 if (sizeBytes < 0) {
2903                     getErrPrintWriter().println("Unable to get size of: " + inPath);
2904                     return -1;
2905                 }
2906             } else {
2907                 fd = ParcelFileDescriptor.dup(getInFileDescriptor());
2908             }
2909             if (sizeBytes <= 0) {
2910                 getErrPrintWriter().println("Error: must specify a APK size");
2911                 return 1;
2912             }
2913 
2914             session = new PackageInstaller.Session(
2915                     mInterface.getPackageInstaller().openSession(sessionId));
2916             session.write(splitName, 0, sizeBytes, fd);
2917 
2918             if (logSuccess) {
2919                 pw.println("Success: streamed " + sizeBytes + " bytes");
2920             }
2921             return 0;
2922         } catch (IOException e) {
2923             getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
2924             return 1;
2925         } finally {
2926             IoUtils.closeQuietly(session);
2927         }
2928     }
2929 
doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)2930     private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
2931             throws RemoteException {
2932         final PrintWriter pw = getOutPrintWriter();
2933         PackageInstaller.Session session = null;
2934         try {
2935             session = new PackageInstaller.Session(
2936                     mInterface.getPackageInstaller().openSession(parentId));
2937             if (!session.isMultiPackage()) {
2938                 getErrPrintWriter().println(
2939                         "Error: parent session ID is not a multi-package session");
2940                 return 1;
2941             }
2942             for (int i = 0; i < sessionIds.length; i++) {
2943                 session.addChildSessionId(sessionIds[i]);
2944             }
2945             if (logSuccess) {
2946                 pw.println("Success");
2947             }
2948             return 0;
2949         } finally {
2950             IoUtils.closeQuietly(session);
2951         }
2952     }
2953 
doRemoveSplit(int sessionId, String splitName, boolean logSuccess)2954     private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
2955             throws RemoteException {
2956         final PrintWriter pw = getOutPrintWriter();
2957         PackageInstaller.Session session = null;
2958         try {
2959             session = new PackageInstaller.Session(
2960                     mInterface.getPackageInstaller().openSession(sessionId));
2961             session.removeSplit(splitName);
2962 
2963             if (logSuccess) {
2964                 pw.println("Success");
2965             }
2966             return 0;
2967         } catch (IOException e) {
2968             pw.println("Error: failed to remove split; " + e.getMessage());
2969             return 1;
2970         } finally {
2971             IoUtils.closeQuietly(session);
2972         }
2973     }
2974 
doCommitSession(int sessionId, boolean logSuccess)2975     private int doCommitSession(int sessionId, boolean logSuccess)
2976             throws RemoteException {
2977 
2978         final PrintWriter pw = getOutPrintWriter();
2979         PackageInstaller.Session session = null;
2980         try {
2981             session = new PackageInstaller.Session(
2982                     mInterface.getPackageInstaller().openSession(sessionId));
2983             if (!session.isMultiPackage() && !session.isStaged()) {
2984                 // Sanity check that all .dm files match an apk.
2985                 // (The installer does not support standalone .dm files and will not process them.)
2986                 try {
2987                     DexMetadataHelper.validateDexPaths(session.getNames());
2988                 } catch (IllegalStateException | IOException e) {
2989                     pw.println(
2990                             "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
2991                 }
2992             }
2993             final LocalIntentReceiver receiver = new LocalIntentReceiver();
2994             session.commit(receiver.getIntentSender());
2995             final Intent result = receiver.getResult();
2996             final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
2997                     PackageInstaller.STATUS_FAILURE);
2998             if (status == PackageInstaller.STATUS_SUCCESS) {
2999                 if (logSuccess) {
3000                     pw.println("Success");
3001                 }
3002             } else {
3003                 pw.println("Failure ["
3004                         + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
3005             }
3006             return status;
3007         } finally {
3008             IoUtils.closeQuietly(session);
3009         }
3010     }
3011 
doAbandonSession(int sessionId, boolean logSuccess)3012     private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException {
3013         final PrintWriter pw = getOutPrintWriter();
3014         PackageInstaller.Session session = null;
3015         try {
3016             session = new PackageInstaller.Session(
3017                     mInterface.getPackageInstaller().openSession(sessionId));
3018             session.abandon();
3019             if (logSuccess) {
3020                 pw.println("Success");
3021             }
3022             return 0;
3023         } finally {
3024             IoUtils.closeQuietly(session);
3025         }
3026     }
3027 
doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, boolean summary, int startProtectionLevel, int endProtectionLevel)3028     private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
3029             boolean summary, int startProtectionLevel, int endProtectionLevel)
3030                     throws RemoteException {
3031         final PrintWriter pw = getOutPrintWriter();
3032         final int groupCount = groupList.size();
3033         for (int i = 0; i < groupCount; i++) {
3034             String groupName = groupList.get(i);
3035             String prefix = "";
3036             if (groups) {
3037                 if (i > 0) {
3038                     pw.println("");
3039                 }
3040                 if (groupName != null) {
3041                     PermissionGroupInfo pgi =
3042                             mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
3043                     if (summary) {
3044                         Resources res = getResources(pgi);
3045                         if (res != null) {
3046                             pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
3047                         } else {
3048                             pw.print(pgi.name + ": ");
3049 
3050                         }
3051                     } else {
3052                         pw.println((labels ? "+ " : "") + "group:" + pgi.name);
3053                         if (labels) {
3054                             pw.println("  package:" + pgi.packageName);
3055                             Resources res = getResources(pgi);
3056                             if (res != null) {
3057                                 pw.println("  label:"
3058                                         + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
3059                                 pw.println("  description:"
3060                                         + loadText(pgi, pgi.descriptionRes,
3061                                                 pgi.nonLocalizedDescription));
3062                             }
3063                         }
3064                     }
3065                 } else {
3066                     pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
3067                 }
3068                 prefix = "  ";
3069             }
3070             List<PermissionInfo> ps =
3071                     mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
3072             final int count = ps.size();
3073             boolean first = true;
3074             for (int p = 0 ; p < count ; p++) {
3075                 PermissionInfo pi = ps.get(p);
3076                 if (groups && groupName == null && pi.group != null) {
3077                     continue;
3078                 }
3079                 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
3080                 if (base < startProtectionLevel
3081                         || base > endProtectionLevel) {
3082                     continue;
3083                 }
3084                 if (summary) {
3085                     if (first) {
3086                         first = false;
3087                     } else {
3088                         pw.print(", ");
3089                     }
3090                     Resources res = getResources(pi);
3091                     if (res != null) {
3092                         pw.print(loadText(pi, pi.labelRes,
3093                                 pi.nonLocalizedLabel));
3094                     } else {
3095                         pw.print(pi.name);
3096                     }
3097                 } else {
3098                     pw.println(prefix + (labels ? "+ " : "")
3099                             + "permission:" + pi.name);
3100                     if (labels) {
3101                         pw.println(prefix + "  package:" + pi.packageName);
3102                         Resources res = getResources(pi);
3103                         if (res != null) {
3104                             pw.println(prefix + "  label:"
3105                                     + loadText(pi, pi.labelRes,
3106                                             pi.nonLocalizedLabel));
3107                             pw.println(prefix + "  description:"
3108                                     + loadText(pi, pi.descriptionRes,
3109                                             pi.nonLocalizedDescription));
3110                         }
3111                         pw.println(prefix + "  protectionLevel:"
3112                                 + PermissionInfo.protectionToString(pi.protectionLevel));
3113                     }
3114                 }
3115             }
3116 
3117             if (summary) {
3118                 pw.println("");
3119             }
3120         }
3121     }
3122 
loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)3123     private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
3124             throws RemoteException {
3125         if (nonLocalized != null) {
3126             return nonLocalized.toString();
3127         }
3128         if (res != 0) {
3129             Resources r = getResources(pii);
3130             if (r != null) {
3131                 try {
3132                     return r.getString(res);
3133                 } catch (Resources.NotFoundException e) {
3134                 }
3135             }
3136         }
3137         return null;
3138     }
3139 
getResources(PackageItemInfo pii)3140     private Resources getResources(PackageItemInfo pii) throws RemoteException {
3141         Resources res = mResourceCache.get(pii.packageName);
3142         if (res != null) return res;
3143 
3144         ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
3145         AssetManager am = new AssetManager();
3146         am.addAssetPath(ai.publicSourceDir);
3147         res = new Resources(am, null, null);
3148         mResourceCache.put(pii.packageName, res);
3149         return res;
3150     }
3151 
3152     @Override
onHelp()3153     public void onHelp() {
3154         final PrintWriter pw = getOutPrintWriter();
3155         pw.println("Package manager (package) commands:");
3156         pw.println("  help");
3157         pw.println("    Print this help text.");
3158         pw.println("");
3159         pw.println("  path [--user USER_ID] PACKAGE");
3160         pw.println("    Print the path to the .apk of the given PACKAGE.");
3161         pw.println("");
3162         pw.println("  dump PACKAGE");
3163         pw.println("    Print various system state associated with the given PACKAGE.");
3164         pw.println("");
3165         pw.println("  list features");
3166         pw.println("    Prints all features of the system.");
3167         pw.println("");
3168         pw.println("  has-feature FEATURE_NAME [version]");
3169         pw.println("    Prints true and returns exit status 0 when system has a FEATURE_NAME,");
3170         pw.println("    otherwise prints false and returns exit status 1");
3171         pw.println("");
3172         pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
3173         pw.println("    Prints all test packages; optionally only those targeting TARGET-PACKAGE");
3174         pw.println("    Options:");
3175         pw.println("      -f: dump the name of the .apk file containing the test package");
3176         pw.println("");
3177         pw.println("  list libraries");
3178         pw.println("    Prints all system libraries.");
3179         pw.println("");
3180         pw.println("  list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] ");
3181         pw.println("      [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]");
3182         pw.println("    Prints all packages; optionally only those whose name contains");
3183         pw.println("    the text in FILTER.  Options are:");
3184         pw.println("      -f: see their associated file");
3185         pw.println("      -a: all known packages (but excluding APEXes)");
3186         pw.println("      -d: filter to only show disabled packages");
3187         pw.println("      -e: filter to only show enabled packages");
3188         pw.println("      -s: filter to only show system packages");
3189         pw.println("      -3: filter to only show third party packages");
3190         pw.println("      -i: see the installer for the packages");
3191         pw.println("      -l: ignored (used for compatibility with older releases)");
3192         pw.println("      -U: also show the package UID");
3193         pw.println("      -u: also include uninstalled packages");
3194         pw.println("      --show-versioncode: also show the version code");
3195         pw.println("      --apex-only: only show APEX packages");
3196         pw.println("      --uid UID: filter to only show packages with the given UID");
3197         pw.println("      --user USER_ID: only list packages belonging to the given user");
3198         pw.println("");
3199         pw.println("  list permission-groups");
3200         pw.println("    Prints all known permission groups.");
3201         pw.println("");
3202         pw.println("  list permissions [-g] [-f] [-d] [-u] [GROUP]");
3203         pw.println("    Prints all known permissions; optionally only those in GROUP.  Options are:");
3204         pw.println("      -g: organize by group");
3205         pw.println("      -f: print all information");
3206         pw.println("      -s: short summary");
3207         pw.println("      -d: only list dangerous permissions");
3208         pw.println("      -u: list only the permissions users will see");
3209         pw.println("");
3210         pw.println("  list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]");
3211         pw.println("    Displays list of all staged sessions on device.");
3212         pw.println("      --only-ready: show only staged sessions that are ready");
3213         pw.println("      --only-sessionid: show only sessionId of each session");
3214         pw.println("      --only-parent: hide all children sessions");
3215         pw.println("");
3216         pw.println("  resolve-activity [--brief] [--components] [--query-flags FLAGS]");
3217         pw.println("       [--user USER_ID] INTENT");
3218         pw.println("    Prints the activity that resolves to the given INTENT.");
3219         pw.println("");
3220         pw.println("  query-activities [--brief] [--components] [--query-flags FLAGS]");
3221         pw.println("       [--user USER_ID] INTENT");
3222         pw.println("    Prints all activities that can handle the given INTENT.");
3223         pw.println("");
3224         pw.println("  query-services [--brief] [--components] [--query-flags FLAGS]");
3225         pw.println("       [--user USER_ID] INTENT");
3226         pw.println("    Prints all services that can handle the given INTENT.");
3227         pw.println("");
3228         pw.println("  query-receivers [--brief] [--components] [--query-flags FLAGS]");
3229         pw.println("       [--user USER_ID] INTENT");
3230         pw.println("    Prints all broadcast receivers that can handle the given INTENT.");
3231         pw.println("");
3232         pw.println("  install [-lrtfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
3233         pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
3234         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3235         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
3236         pw.println("       [--preload] [--instantapp] [--full] [--dont-kill]");
3237         pw.println("       [--enable-rollback]");
3238         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
3239         pw.println("       [--apex] [--wait TIMEOUT]");
3240         pw.println("       [PATH|-]");
3241         pw.println("    Install an application.  Must provide the apk data to install, either as a");
3242         pw.println("    file path or '-' to read from stdin.  Options are:");
3243         pw.println("      -l: forward lock application");
3244         pw.println("      -R: disallow replacement of existing application");
3245         pw.println("      -t: allow test packages");
3246         pw.println("      -i: specify package name of installer owning the app");
3247         pw.println("      -f: install application on internal flash");
3248         pw.println("      -d: allow version code downgrade (debuggable packages only)");
3249         pw.println("      -p: partial application install (new split on top of existing pkg)");
3250         pw.println("      -g: grant all runtime permissions");
3251         pw.println("      -S: size in bytes of package, required for stdin");
3252         pw.println("      --user: install under the given user.");
3253         pw.println("      --dont-kill: installing a new feature split, don't kill running app");
3254         pw.println("      --restrict-permissions: don't whitelist restricted permissions at install");
3255         pw.println("      --originating-uri: set URI where app was downloaded from");
3256         pw.println("      --referrer: set URI that instigated the install of the app");
3257         pw.println("      --pkg: specify expected package name of app being installed");
3258         pw.println("      --abi: override the default ABI of the platform");
3259         pw.println("      --instantapp: cause the app to be installed as an ephemeral install app");
3260         pw.println("      --full: cause the app to be installed as a non-ephemeral full app");
3261         pw.println("      --install-location: force the install location:");
3262         pw.println("          0=auto, 1=internal only, 2=prefer external");
3263         pw.println("      --install-reason: indicates why the app is being installed:");
3264         pw.println("          0=unknown, 1=admin policy, 2=device restore,");
3265         pw.println("          3=device setup, 4=user request");
3266         pw.println("      --force-uuid: force install on to disk volume with given UUID");
3267         pw.println("      --apex: install an .apex file, not an .apk");
3268         pw.println("      --wait: when performing staged install, wait TIMEOUT milliseconds");
3269         pw.println("          for pre-reboot verification to complete. If TIMEOUT is not");
3270         pw.println("          specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
3271         pw.println("");
3272         pw.println("  install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
3273         pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
3274         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
3275         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
3276         pw.println("       [--preload] [--instantapp] [--full] [--dont-kill]");
3277         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]");
3278         pw.println("       [--multi-package] [--staged]");
3279         pw.println("    Like \"install\", but starts an install session.  Use \"install-write\"");
3280         pw.println("    to push data into the session, and \"install-commit\" to finish.");
3281         pw.println("");
3282         pw.println("  install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]");
3283         pw.println("    Write an apk into the given install session.  If the path is '-', data");
3284         pw.println("    will be read from stdin.  Options are:");
3285         pw.println("      -S: size in bytes of package, required for stdin");
3286         pw.println("");
3287         pw.println("  install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
3288         pw.println("    Add one or more session IDs to a multi-package session.");
3289         pw.println("");
3290         pw.println("  install-commit SESSION_ID");
3291         pw.println("    Commit the given active install session, installing the app.");
3292         pw.println("");
3293         pw.println("  install-abandon SESSION_ID");
3294         pw.println("    Delete the given active install session.");
3295         pw.println("");
3296         pw.println("  set-install-location LOCATION");
3297         pw.println("    Changes the default install location.  NOTE this is only intended for debugging;");
3298         pw.println("    using this can cause applications to break and other undersireable behavior.");
3299         pw.println("    LOCATION is one of:");
3300         pw.println("    0 [auto]: Let system decide the best location");
3301         pw.println("    1 [internal]: Install on internal device storage");
3302         pw.println("    2 [external]: Install on external media");
3303         pw.println("");
3304         pw.println("  get-install-location");
3305         pw.println("    Returns the current install location: 0, 1 or 2 as per set-install-location.");
3306         pw.println("");
3307         pw.println("  move-package PACKAGE [internal|UUID]");
3308         pw.println("");
3309         pw.println("  move-primary-storage [internal|UUID]");
3310         pw.println("");
3311         pw.println("  pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE [SPLIT]");
3312         pw.println("    Remove the given package name from the system.  May remove an entire app");
3313         pw.println("    if no SPLIT name is specified, otherwise will remove only the split of the");
3314         pw.println("    given app.  Options are:");
3315         pw.println("      -k: keep the data and cache directories around after package removal.");
3316         pw.println("      --user: remove the app from the given user.");
3317         pw.println("      --versionCode: only uninstall if the app has the given version code.");
3318         pw.println("");
3319         pw.println("  clear [--user USER_ID] PACKAGE");
3320         pw.println("    Deletes all data associated with a package.");
3321         pw.println("");
3322         pw.println("  enable [--user USER_ID] PACKAGE_OR_COMPONENT");
3323         pw.println("  disable [--user USER_ID] PACKAGE_OR_COMPONENT");
3324         pw.println("  disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
3325         pw.println("  disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
3326         pw.println("  default-state [--user USER_ID] PACKAGE_OR_COMPONENT");
3327         pw.println("    These commands change the enabled state of a given package or");
3328         pw.println("    component (written as \"package/class\").");
3329         pw.println("");
3330         pw.println("  hide [--user USER_ID] PACKAGE_OR_COMPONENT");
3331         pw.println("  unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
3332         pw.println("");
3333         pw.println("  suspend [--user USER_ID] TARGET-PACKAGE");
3334         pw.println("    Suspends the specified package (as user).");
3335         pw.println("");
3336         pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
3337         pw.println("    Unsuspends the specified package (as user).");
3338         pw.println("");
3339         pw.println("  grant [--user USER_ID] PACKAGE PERMISSION");
3340         pw.println("  revoke [--user USER_ID] PACKAGE PERMISSION");
3341         pw.println("    These commands either grant or revoke permissions to apps.  The permissions");
3342         pw.println("    must be declared as used in the app's manifest, be runtime permissions");
3343         pw.println("    (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
3344         pw.println("");
3345         pw.println("  reset-permissions");
3346         pw.println("    Revert all runtime permissions to their default state.");
3347         pw.println("");
3348         pw.println("  set-permission-enforced PERMISSION [true|false]");
3349         pw.println("");
3350         pw.println("  get-privapp-permissions TARGET-PACKAGE");
3351         pw.println("    Prints all privileged permissions for a package.");
3352         pw.println("");
3353         pw.println("  get-privapp-deny-permissions TARGET-PACKAGE");
3354         pw.println("    Prints all privileged permissions that are denied for a package.");
3355         pw.println("");
3356         pw.println("  get-oem-permissions TARGET-PACKAGE");
3357         pw.println("    Prints all OEM permissions for a package.");
3358         pw.println("");
3359         pw.println("  set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
3360         pw.println("  get-app-link [--user USER_ID] PACKAGE");
3361         pw.println("");
3362         pw.println("  trim-caches DESIRED_FREE_SPACE [internal|UUID]");
3363         pw.println("    Trim cache files to reach the given free space.");
3364         pw.println("");
3365         pw.println("  list users");
3366         pw.println("    Lists the current users.");
3367         pw.println("");
3368         pw.println("  create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
3369         pw.println("      [--guest] [--pre-create-only] USER_NAME");
3370         pw.println("    Create a new user with the given USER_NAME, printing the new user identifier");
3371         pw.println("    of the user.");
3372         pw.println("");
3373         pw.println("  remove-user USER_ID");
3374         pw.println("    Remove the user with the given USER_IDENTIFIER, deleting all data");
3375         pw.println("    associated with that user");
3376         pw.println("");
3377         pw.println("  set-user-restriction [--user USER_ID] RESTRICTION VALUE");
3378         pw.println("");
3379         pw.println("  get-max-users");
3380         pw.println("");
3381         pw.println("  get-max-running-users");
3382         pw.println("");
3383         pw.println("  compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
3384         pw.println("          [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
3385         pw.println("    Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".  Options are:");
3386         pw.println("      -a: compile all packages");
3387         pw.println("      -c: clear profile data before compiling");
3388         pw.println("      -f: force compilation even if not needed");
3389         pw.println("      -m: select compilation mode");
3390         pw.println("          MODE is one of the dex2oat compiler filters:");
3391         pw.println("            assume-verified");
3392         pw.println("            extract");
3393         pw.println("            verify");
3394         pw.println("            quicken");
3395         pw.println("            space-profile");
3396         pw.println("            space");
3397         pw.println("            speed-profile");
3398         pw.println("            speed");
3399         pw.println("            everything");
3400         pw.println("      -r: select compilation reason");
3401         pw.println("          REASON is one of:");
3402         for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
3403             pw.println("            " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
3404         }
3405         pw.println("      --reset: restore package to its post-install state");
3406         pw.println("      --check-prof (true | false): look at profiles when doing dexopt?");
3407         pw.println("      --secondary-dex: compile app secondary dex files");
3408         pw.println("      --split SPLIT: compile only the given split name");
3409         pw.println("      --compile-layouts: compile layout resources for faster inflation");
3410         pw.println("");
3411         pw.println("  force-dex-opt PACKAGE");
3412         pw.println("    Force immediate execution of dex opt for the given PACKAGE.");
3413         pw.println("");
3414         pw.println("  bg-dexopt-job");
3415         pw.println("    Execute the background optimizations immediately.");
3416         pw.println("    Note that the command only runs the background optimizer logic. It may");
3417         pw.println("    overlap with the actual job but the job scheduler will not be able to");
3418         pw.println("    cancel it. It will also run even if the device is not in the idle");
3419         pw.println("    maintenance mode.");
3420         pw.println("");
3421         pw.println("  reconcile-secondary-dex-files TARGET-PACKAGE");
3422         pw.println("    Reconciles the package secondary dex files with the generated oat files.");
3423         pw.println("");
3424         pw.println("  dump-profiles TARGET-PACKAGE");
3425         pw.println("    Dumps method/class profile files to");
3426         pw.println("    " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + "TARGET-PACKAGE.txt");
3427         pw.println("");
3428         pw.println("  snapshot-profile TARGET-PACKAGE [--code-path path]");
3429         pw.println("    Take a snapshot of the package profiles to");
3430         pw.println("    " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION
3431                 + "TARGET-PACKAGE[-code-path].prof");
3432         pw.println("    If TARGET-PACKAGE=android it will take a snapshot of the boot image");
3433         pw.println("");
3434         pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
3435         pw.println("    Set the default home activity (aka launcher).");
3436         pw.println("    TARGET-COMPONENT can be a package name (com.package.my) or a full");
3437         pw.println("    component (com.package.my/component.name). However, only the package name");
3438         pw.println("    matters: the actual component used will be determined automatically from");
3439         pw.println("    the package.");
3440         pw.println("");
3441         pw.println("  set-installer PACKAGE INSTALLER");
3442         pw.println("    Set installer package name");
3443         pw.println("");
3444         pw.println("  get-instantapp-resolver");
3445         pw.println("    Return the name of the component that is the current instant app installer.");
3446         pw.println("");
3447         pw.println("  set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]");
3448         pw.println("    Mark the app as harmful with the given warning message.");
3449         pw.println("");
3450         pw.println("  get-harmful-app-warning [--user <USER_ID>] <PACKAGE>");
3451         pw.println("    Return the harmful app warning message for the given app, if present");
3452         pw.println();
3453         pw.println("  uninstall-system-updates");
3454         pw.println("    Remove updates to all system applications and fall back to their /system " +
3455                 "version.");
3456         pw.println("");
3457         pw.println("  get-moduleinfo [--all | --installed] [module-name]");
3458         pw.println("    Displays module info. If module-name is specified only that info is shown");
3459         pw.println("    By default, without any argument only installed modules are shown.");
3460         pw.println("      --all: show all module info");
3461         pw.println("      --installed: show only installed modules");
3462         pw.println("");
3463         Intent.printIntentArgsHelp(pw , "");
3464     }
3465 
3466     private static class LocalIntentReceiver {
3467         private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
3468 
3469         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
3470             @Override
3471             public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
3472                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
3473                 try {
3474                     mResult.offer(intent, 5, TimeUnit.SECONDS);
3475                 } catch (InterruptedException e) {
3476                     throw new RuntimeException(e);
3477                 }
3478             }
3479         };
3480 
getIntentSender()3481         public IntentSender getIntentSender() {
3482             return new IntentSender((IIntentSender) mLocalSender);
3483         }
3484 
getResult()3485         public Intent getResult() {
3486             try {
3487                 return mResult.take();
3488             } catch (InterruptedException e) {
3489                 throw new RuntimeException(e);
3490             }
3491         }
3492     }
3493 }
3494