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