1/*
2 * Copyright (C) 2007 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
17package com.android.commands.pm;
18
19import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
20import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
21import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
22import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
23import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
24
25import android.app.ActivityManager;
26import android.app.ActivityManagerNative;
27import android.app.IActivityManager;
28import android.app.PackageInstallObserver;
29import android.content.ComponentName;
30import android.content.IIntentReceiver;
31import android.content.IIntentSender;
32import android.content.Intent;
33import android.content.IntentSender;
34import android.content.pm.ApplicationInfo;
35import android.content.pm.FeatureInfo;
36import android.content.pm.IPackageDataObserver;
37import android.content.pm.IPackageInstaller;
38import android.content.pm.IPackageManager;
39import android.content.pm.InstrumentationInfo;
40import android.content.pm.PackageInfo;
41import android.content.pm.PackageInstaller;
42import android.content.pm.PackageInstaller.SessionInfo;
43import android.content.pm.PackageInstaller.SessionParams;
44import android.content.pm.PackageItemInfo;
45import android.content.pm.PackageManager;
46import android.content.pm.ParceledListSlice;
47import android.content.pm.PermissionGroupInfo;
48import android.content.pm.PermissionInfo;
49import android.content.pm.UserInfo;
50import android.content.pm.VerificationParams;
51import android.content.res.AssetManager;
52import android.content.res.Resources;
53import android.net.Uri;
54import android.os.Build;
55import android.os.Bundle;
56import android.os.IUserManager;
57import android.os.RemoteException;
58import android.os.ServiceManager;
59import android.os.SystemClock;
60import android.os.UserHandle;
61import android.os.UserManager;
62import android.text.TextUtils;
63import android.text.format.DateUtils;
64import android.util.Log;
65
66import libcore.io.IoUtils;
67
68import com.android.internal.content.PackageHelper;
69import com.android.internal.util.ArrayUtils;
70import com.android.internal.util.SizedInputStream;
71
72import java.io.File;
73import java.io.FileDescriptor;
74import java.io.FileInputStream;
75import java.io.IOException;
76import java.io.InputStream;
77import java.io.OutputStream;
78import java.lang.reflect.Field;
79import java.lang.reflect.Modifier;
80import java.util.ArrayList;
81import java.util.Collections;
82import java.util.Comparator;
83import java.util.List;
84import java.util.WeakHashMap;
85import java.util.concurrent.SynchronousQueue;
86import java.util.concurrent.TimeUnit;
87
88public final class Pm {
89    private static final String TAG = "Pm";
90
91    IPackageManager mPm;
92    IPackageInstaller mInstaller;
93    IUserManager mUm;
94
95    private WeakHashMap<String, Resources> mResourceCache
96            = new WeakHashMap<String, Resources>();
97
98    private String[] mArgs;
99    private int mNextArg;
100    private String mCurArgData;
101
102    private static final String PM_NOT_RUNNING_ERR =
103        "Error: Could not access the Package Manager.  Is the system running?";
104
105    public static void main(String[] args) {
106        int exitCode = 1;
107        try {
108            exitCode = new Pm().run(args);
109        } catch (Exception e) {
110            Log.e(TAG, "Error", e);
111            System.err.println("Error: " + e);
112            if (e instanceof RemoteException) {
113                System.err.println(PM_NOT_RUNNING_ERR);
114            }
115        }
116        System.exit(exitCode);
117    }
118
119    public int run(String[] args) throws IOException, RemoteException {
120        boolean validCommand = false;
121        if (args.length < 1) {
122            return showUsage();
123        }
124
125        mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
126        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
127        if (mPm == null) {
128            System.err.println(PM_NOT_RUNNING_ERR);
129            return 1;
130        }
131        mInstaller = mPm.getPackageInstaller();
132
133        mArgs = args;
134        String op = args[0];
135        mNextArg = 1;
136
137        if ("list".equals(op)) {
138            return runList();
139        }
140
141        if ("path".equals(op)) {
142            return runPath();
143        }
144
145        if ("dump".equals(op)) {
146            return runDump();
147        }
148
149        if ("install".equals(op)) {
150            return runInstall();
151        }
152
153        if ("install-create".equals(op)) {
154            return runInstallCreate();
155        }
156
157        if ("install-write".equals(op)) {
158            return runInstallWrite();
159        }
160
161        if ("install-commit".equals(op)) {
162            return runInstallCommit();
163        }
164
165        if ("install-abandon".equals(op) || "install-destroy".equals(op)) {
166            return runInstallAbandon();
167        }
168
169        if ("set-installer".equals(op)) {
170            return runSetInstaller();
171        }
172
173        if ("uninstall".equals(op)) {
174            return runUninstall();
175        }
176
177        if ("clear".equals(op)) {
178            return runClear();
179        }
180
181        if ("enable".equals(op)) {
182            return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
183        }
184
185        if ("disable".equals(op)) {
186            return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
187        }
188
189        if ("disable-user".equals(op)) {
190            return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
191        }
192
193        if ("disable-until-used".equals(op)) {
194            return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
195        }
196
197        if ("hide".equals(op)) {
198            return runSetHiddenSetting(true);
199        }
200
201        if ("unhide".equals(op)) {
202            return runSetHiddenSetting(false);
203        }
204
205        if ("grant".equals(op)) {
206            return runGrantRevokePermission(true);
207        }
208
209        if ("revoke".equals(op)) {
210            return runGrantRevokePermission(false);
211        }
212
213        if ("reset-permissions".equals(op)) {
214            return runResetPermissions();
215        }
216
217        if ("set-permission-enforced".equals(op)) {
218            return runSetPermissionEnforced();
219        }
220
221        if ("set-app-link".equals(op)) {
222            return runSetAppLink();
223        }
224
225        if ("get-app-link".equals(op)) {
226            return runGetAppLink();
227        }
228
229        if ("set-install-location".equals(op)) {
230            return runSetInstallLocation();
231        }
232
233        if ("get-install-location".equals(op)) {
234            return runGetInstallLocation();
235        }
236
237        if ("trim-caches".equals(op)) {
238            return runTrimCaches();
239        }
240
241        if ("create-user".equals(op)) {
242            return runCreateUser();
243        }
244
245        if ("remove-user".equals(op)) {
246            return runRemoveUser();
247        }
248
249        if ("get-max-users".equals(op)) {
250            return runGetMaxUsers();
251        }
252
253        if ("force-dex-opt".equals(op)) {
254            return runForceDexOpt();
255        }
256
257        if ("move-package".equals(op)) {
258            return runMovePackage();
259        }
260
261        if ("move-primary-storage".equals(op)) {
262            return runMovePrimaryStorage();
263        }
264
265        try {
266            if (args.length == 1) {
267                if (args[0].equalsIgnoreCase("-l")) {
268                    validCommand = true;
269                    return runListPackages(false);
270                } else if (args[0].equalsIgnoreCase("-lf")){
271                    validCommand = true;
272                    return runListPackages(true);
273                }
274            } else if (args.length == 2) {
275                if (args[0].equalsIgnoreCase("-p")) {
276                    validCommand = true;
277                    return displayPackageFilePath(args[1]);
278                }
279            }
280            return 1;
281        } finally {
282            if (validCommand == false) {
283                if (op != null) {
284                    System.err.println("Error: unknown command '" + op + "'");
285                }
286                showUsage();
287            }
288        }
289    }
290
291    /**
292     * Execute the list sub-command.
293     *
294     * pm list [package | packages]
295     * pm list permission-groups
296     * pm list permissions
297     * pm list features
298     * pm list libraries
299     * pm list instrumentation
300     */
301    private int runList() {
302        String type = nextArg();
303        if (type == null) {
304            System.err.println("Error: didn't specify type of data to list");
305            return 1;
306        }
307        if ("package".equals(type) || "packages".equals(type)) {
308            return runListPackages(false);
309        } else if ("permission-groups".equals(type)) {
310            return runListPermissionGroups();
311        } else if ("permissions".equals(type)) {
312            return runListPermissions();
313        } else if ("features".equals(type)) {
314            return runListFeatures();
315        } else if ("libraries".equals(type)) {
316            return runListLibraries();
317        } else if ("instrumentation".equals(type)) {
318            return runListInstrumentation();
319        } else if ("users".equals(type)) {
320            return runListUsers();
321        } else {
322            System.err.println("Error: unknown list type '" + type + "'");
323            return 1;
324        }
325    }
326
327    /**
328     * Lists all the installed packages.
329     */
330    private int runListPackages(boolean showApplicationPackage) {
331        int getFlags = 0;
332        boolean listDisabled = false, listEnabled = false;
333        boolean listSystem = false, listThirdParty = false;
334        boolean listInstaller = false;
335        int userId = UserHandle.USER_OWNER;
336        try {
337            String opt;
338            while ((opt=nextOption()) != null) {
339                if (opt.equals("-l")) {
340                    // old compat
341                } else if (opt.equals("-lf")) {
342                    showApplicationPackage = true;
343                } else if (opt.equals("-f")) {
344                    showApplicationPackage = true;
345                } else if (opt.equals("-d")) {
346                    listDisabled = true;
347                } else if (opt.equals("-e")) {
348                    listEnabled = true;
349                } else if (opt.equals("-s")) {
350                    listSystem = true;
351                } else if (opt.equals("-3")) {
352                    listThirdParty = true;
353                } else if (opt.equals("-i")) {
354                    listInstaller = true;
355                } else if (opt.equals("--user")) {
356                    userId = Integer.parseInt(nextArg());
357                } else if (opt.equals("-u")) {
358                    getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
359                } else {
360                    System.err.println("Error: Unknown option: " + opt);
361                    return 1;
362                }
363            }
364        } catch (RuntimeException ex) {
365            System.err.println("Error: " + ex.toString());
366            return 1;
367        }
368
369        String filter = nextArg();
370
371        try {
372            final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags, userId);
373
374            int count = packages.size();
375            for (int p = 0 ; p < count ; p++) {
376                PackageInfo info = packages.get(p);
377                if (filter != null && !info.packageName.contains(filter)) {
378                    continue;
379                }
380                final boolean isSystem =
381                        (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
382                if ((!listDisabled || !info.applicationInfo.enabled) &&
383                        (!listEnabled || info.applicationInfo.enabled) &&
384                        (!listSystem || isSystem) &&
385                        (!listThirdParty || !isSystem)) {
386                    System.out.print("package:");
387                    if (showApplicationPackage) {
388                        System.out.print(info.applicationInfo.sourceDir);
389                        System.out.print("=");
390                    }
391                    System.out.print(info.packageName);
392                    if (listInstaller) {
393                        System.out.print("  installer=");
394                        System.out.print(mPm.getInstallerPackageName(info.packageName));
395                    }
396                    System.out.println();
397                }
398            }
399            return 0;
400        } catch (RemoteException e) {
401            System.err.println(e.toString());
402            System.err.println(PM_NOT_RUNNING_ERR);
403            return 1;
404        }
405    }
406
407    @SuppressWarnings("unchecked")
408    private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
409            throws RemoteException {
410        ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId);
411        return slice.getList();
412    }
413
414    /**
415     * Lists all of the features supported by the current device.
416     *
417     * pm list features
418     */
419    private int runListFeatures() {
420        try {
421            List<FeatureInfo> list = new ArrayList<FeatureInfo>();
422            FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
423            for (int i=0; i<rawList.length; i++) {
424                list.add(rawList[i]);
425            }
426
427
428            // Sort by name
429            Collections.sort(list, new Comparator<FeatureInfo>() {
430                public int compare(FeatureInfo o1, FeatureInfo o2) {
431                    if (o1.name == o2.name) return 0;
432                    if (o1.name == null) return -1;
433                    if (o2.name == null) return 1;
434                    return o1.name.compareTo(o2.name);
435                }
436            });
437
438            int count = (list != null) ? list.size() : 0;
439            for (int p = 0; p < count; p++) {
440                FeatureInfo fi = list.get(p);
441                System.out.print("feature:");
442                if (fi.name != null) System.out.println(fi.name);
443                else System.out.println("reqGlEsVersion=0x"
444                        + Integer.toHexString(fi.reqGlEsVersion));
445            }
446            return 0;
447        } catch (RemoteException e) {
448            System.err.println(e.toString());
449            System.err.println(PM_NOT_RUNNING_ERR);
450            return 1;
451        }
452    }
453
454    /**
455     * Lists all of the libraries supported by the current device.
456     *
457     * pm list libraries
458     */
459    private int runListLibraries() {
460        try {
461            List<String> list = new ArrayList<String>();
462            String[] rawList = mPm.getSystemSharedLibraryNames();
463            for (int i=0; i<rawList.length; i++) {
464                list.add(rawList[i]);
465            }
466
467
468            // Sort by name
469            Collections.sort(list, new Comparator<String>() {
470                public int compare(String o1, String o2) {
471                    if (o1 == o2) return 0;
472                    if (o1 == null) return -1;
473                    if (o2 == null) return 1;
474                    return o1.compareTo(o2);
475                }
476            });
477
478            int count = (list != null) ? list.size() : 0;
479            for (int p = 0; p < count; p++) {
480                String lib = list.get(p);
481                System.out.print("library:");
482                System.out.println(lib);
483            }
484            return 0;
485        } catch (RemoteException e) {
486            System.err.println(e.toString());
487            System.err.println(PM_NOT_RUNNING_ERR);
488            return 1;
489        }
490    }
491
492    /**
493     * Lists all of the installed instrumentation, or all for a given package
494     *
495     * pm list instrumentation [package] [-f]
496     */
497    private int runListInstrumentation() {
498        int flags = 0;      // flags != 0 is only used to request meta-data
499        boolean showPackage = false;
500        String targetPackage = null;
501
502        try {
503            String opt;
504            while ((opt=nextArg()) != null) {
505                if (opt.equals("-f")) {
506                    showPackage = true;
507                } else if (opt.charAt(0) != '-') {
508                    targetPackage = opt;
509                } else {
510                    System.err.println("Error: Unknown option: " + opt);
511                    return 1;
512                }
513            }
514        } catch (RuntimeException ex) {
515            System.err.println("Error: " + ex.toString());
516            return 1;
517        }
518
519        try {
520            List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
521
522            // Sort by target package
523            Collections.sort(list, new Comparator<InstrumentationInfo>() {
524                public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
525                    return o1.targetPackage.compareTo(o2.targetPackage);
526                }
527            });
528
529            int count = (list != null) ? list.size() : 0;
530            for (int p = 0; p < count; p++) {
531                InstrumentationInfo ii = list.get(p);
532                System.out.print("instrumentation:");
533                if (showPackage) {
534                    System.out.print(ii.sourceDir);
535                    System.out.print("=");
536                }
537                ComponentName cn = new ComponentName(ii.packageName, ii.name);
538                System.out.print(cn.flattenToShortString());
539                System.out.print(" (target=");
540                System.out.print(ii.targetPackage);
541                System.out.println(")");
542            }
543            return 0;
544        } catch (RemoteException e) {
545            System.err.println(e.toString());
546            System.err.println(PM_NOT_RUNNING_ERR);
547            return 1;
548        }
549    }
550
551    /**
552     * Lists all the known permission groups.
553     */
554    private int runListPermissionGroups() {
555        try {
556            List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
557
558            int count = pgs.size();
559            for (int p = 0 ; p < count ; p++) {
560                PermissionGroupInfo pgi = pgs.get(p);
561                System.out.print("permission group:");
562                System.out.println(pgi.name);
563            }
564            return 0;
565        } catch (RemoteException e) {
566            System.err.println(e.toString());
567            System.err.println(PM_NOT_RUNNING_ERR);
568            return 1;
569        }
570    }
571
572    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
573        if (nonLocalized != null) {
574            return nonLocalized.toString();
575        }
576        if (res != 0) {
577            Resources r = getResources(pii);
578            if (r != null) {
579                try {
580                    return r.getString(res);
581                } catch (Resources.NotFoundException e) {
582                }
583            }
584        }
585        return null;
586    }
587
588    /**
589     * Lists all the permissions in a group.
590     */
591    private int runListPermissions() {
592        try {
593            boolean labels = false;
594            boolean groups = false;
595            boolean userOnly = false;
596            boolean summary = false;
597            boolean dangerousOnly = false;
598            String opt;
599            while ((opt=nextOption()) != null) {
600                if (opt.equals("-f")) {
601                    labels = true;
602                } else if (opt.equals("-g")) {
603                    groups = true;
604                } else if (opt.equals("-s")) {
605                    groups = true;
606                    labels = true;
607                    summary = true;
608                } else if (opt.equals("-u")) {
609                    userOnly = true;
610                } else if (opt.equals("-d")) {
611                    dangerousOnly = true;
612                } else {
613                    System.err.println("Error: Unknown option: " + opt);
614                    return 1;
615                }
616            }
617
618            String grp = nextOption();
619            ArrayList<String> groupList = new ArrayList<String>();
620            if (groups) {
621                List<PermissionGroupInfo> infos =
622                        mPm.getAllPermissionGroups(0);
623                for (int i=0; i<infos.size(); i++) {
624                    groupList.add(infos.get(i).name);
625                }
626                groupList.add(null);
627            } else {
628                groupList.add(grp);
629            }
630
631            if (dangerousOnly) {
632                System.out.println("Dangerous Permissions:");
633                System.out.println("");
634                doListPermissions(groupList, groups, labels, summary,
635                        PermissionInfo.PROTECTION_DANGEROUS,
636                        PermissionInfo.PROTECTION_DANGEROUS);
637                if (userOnly) {
638                    System.out.println("Normal Permissions:");
639                    System.out.println("");
640                    doListPermissions(groupList, groups, labels, summary,
641                            PermissionInfo.PROTECTION_NORMAL,
642                            PermissionInfo.PROTECTION_NORMAL);
643                }
644            } else if (userOnly) {
645                System.out.println("Dangerous and Normal Permissions:");
646                System.out.println("");
647                doListPermissions(groupList, groups, labels, summary,
648                        PermissionInfo.PROTECTION_NORMAL,
649                        PermissionInfo.PROTECTION_DANGEROUS);
650            } else {
651                System.out.println("All Permissions:");
652                System.out.println("");
653                doListPermissions(groupList, groups, labels, summary,
654                        -10000, 10000);
655            }
656            return 0;
657        } catch (RemoteException e) {
658            System.err.println(e.toString());
659            System.err.println(PM_NOT_RUNNING_ERR);
660            return 1;
661        }
662    }
663
664    private void doListPermissions(ArrayList<String> groupList,
665            boolean groups, boolean labels, boolean summary,
666            int startProtectionLevel, int endProtectionLevel)
667            throws RemoteException {
668        for (int i=0; i<groupList.size(); i++) {
669            String groupName = groupList.get(i);
670            String prefix = "";
671            if (groups) {
672                if (i > 0) System.out.println("");
673                if (groupName != null) {
674                    PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
675                            groupName, 0);
676                    if (summary) {
677                        Resources res = getResources(pgi);
678                        if (res != null) {
679                            System.out.print(loadText(pgi, pgi.labelRes,
680                                    pgi.nonLocalizedLabel) + ": ");
681                        } else {
682                            System.out.print(pgi.name + ": ");
683
684                        }
685                    } else {
686                        System.out.println((labels ? "+ " : "")
687                                + "group:" + pgi.name);
688                        if (labels) {
689                            System.out.println("  package:" + pgi.packageName);
690                            Resources res = getResources(pgi);
691                            if (res != null) {
692                                System.out.println("  label:"
693                                        + loadText(pgi, pgi.labelRes,
694                                                pgi.nonLocalizedLabel));
695                                System.out.println("  description:"
696                                        + loadText(pgi, pgi.descriptionRes,
697                                                pgi.nonLocalizedDescription));
698                            }
699                        }
700                    }
701                } else {
702                    System.out.println(((labels && !summary)
703                            ? "+ " : "") + "ungrouped:");
704                }
705                prefix = "  ";
706            }
707            List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
708                    groupList.get(i), 0);
709            int count = ps.size();
710            boolean first = true;
711            for (int p = 0 ; p < count ; p++) {
712                PermissionInfo pi = ps.get(p);
713                if (groups && groupName == null && pi.group != null) {
714                    continue;
715                }
716                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
717                if (base < startProtectionLevel
718                        || base > endProtectionLevel) {
719                    continue;
720                }
721                if (summary) {
722                    if (first) {
723                        first = false;
724                    } else {
725                        System.out.print(", ");
726                    }
727                    Resources res = getResources(pi);
728                    if (res != null) {
729                        System.out.print(loadText(pi, pi.labelRes,
730                                pi.nonLocalizedLabel));
731                    } else {
732                        System.out.print(pi.name);
733                    }
734                } else {
735                    System.out.println(prefix + (labels ? "+ " : "")
736                            + "permission:" + pi.name);
737                    if (labels) {
738                        System.out.println(prefix + "  package:" + pi.packageName);
739                        Resources res = getResources(pi);
740                        if (res != null) {
741                            System.out.println(prefix + "  label:"
742                                    + loadText(pi, pi.labelRes,
743                                            pi.nonLocalizedLabel));
744                            System.out.println(prefix + "  description:"
745                                    + loadText(pi, pi.descriptionRes,
746                                            pi.nonLocalizedDescription));
747                        }
748                        System.out.println(prefix + "  protectionLevel:"
749                                + PermissionInfo.protectionToString(pi.protectionLevel));
750                    }
751                }
752            }
753
754            if (summary) {
755                System.out.println("");
756            }
757        }
758    }
759
760    private int runPath() {
761        String pkg = nextArg();
762        if (pkg == null) {
763            System.err.println("Error: no package specified");
764            return 1;
765        }
766        return displayPackageFilePath(pkg);
767    }
768
769    private int runDump() {
770        String pkg = nextArg();
771        if (pkg == null) {
772            System.err.println("Error: no package specified");
773            return 1;
774        }
775        ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
776        return 0;
777    }
778
779    class LocalPackageInstallObserver extends PackageInstallObserver {
780        boolean finished;
781        int result;
782        String extraPermission;
783        String extraPackage;
784
785        @Override
786        public void onPackageInstalled(String name, int status, String msg, Bundle extras) {
787            synchronized (this) {
788                finished = true;
789                result = status;
790                if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) {
791                    extraPermission = extras.getString(
792                            PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION);
793                    extraPackage = extras.getString(
794                            PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
795                }
796                notifyAll();
797            }
798        }
799    }
800
801    /**
802     * Converts a failure code into a string by using reflection to find a matching constant
803     * in PackageManager.
804     */
805    private String installFailureToString(LocalPackageInstallObserver obs) {
806        final int result = obs.result;
807        Field[] fields = PackageManager.class.getFields();
808        for (Field f: fields) {
809            if (f.getType() == int.class) {
810                int modifiers = f.getModifiers();
811                // only look at public final static fields.
812                if (((modifiers & Modifier.FINAL) != 0) &&
813                        ((modifiers & Modifier.PUBLIC) != 0) &&
814                        ((modifiers & Modifier.STATIC) != 0)) {
815                    String fieldName = f.getName();
816                    if (fieldName.startsWith("INSTALL_FAILED_") ||
817                            fieldName.startsWith("INSTALL_PARSE_FAILED_")) {
818                        // get the int value and compare it to result.
819                        try {
820                            if (result == f.getInt(null)) {
821                                StringBuilder sb = new StringBuilder(64);
822                                sb.append(fieldName);
823                                if (obs.extraPermission != null) {
824                                    sb.append(" perm=");
825                                    sb.append(obs.extraPermission);
826                                }
827                                if (obs.extraPackage != null) {
828                                    sb.append(" pkg=" + obs.extraPackage);
829                                }
830                                return sb.toString();
831                            }
832                        } catch (IllegalAccessException e) {
833                            // this shouldn't happen since we only look for public static fields.
834                        }
835                    }
836                }
837            }
838        }
839
840        // couldn't find a matching constant? return the value
841        return Integer.toString(result);
842    }
843
844    // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
845    private int runSetAppLink() {
846        int userId = UserHandle.USER_OWNER;
847
848        String opt;
849        while ((opt = nextOption()) != null) {
850            if (opt.equals("--user")) {
851                userId = Integer.parseInt(nextOptionData());
852                if (userId < 0) {
853                    System.err.println("Error: user must be >= 0");
854                    return 1;
855                }
856            } else {
857                System.err.println("Error: unknown option: " + opt);
858                showUsage();
859                return 1;
860            }
861        }
862
863        // Package name to act on; required
864        final String pkg = nextArg();
865        if (pkg == null) {
866            System.err.println("Error: no package specified.");
867            showUsage();
868            return 1;
869        }
870
871        // State to apply; {always|ask|never|undefined}, required
872        final String modeString = nextArg();
873        if (modeString == null) {
874            System.err.println("Error: no app link state specified.");
875            showUsage();
876            return 1;
877        }
878
879        final int newMode;
880        switch (modeString.toLowerCase()) {
881            case "undefined":
882                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
883                break;
884
885            case "always":
886                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
887                break;
888
889            case "ask":
890                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
891                break;
892
893            case "always-ask":
894                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
895                break;
896
897            case "never":
898                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
899                break;
900
901            default:
902                System.err.println("Error: unknown app link state '" + modeString + "'");
903                return 1;
904        }
905
906        try {
907            final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
908            if (info == null) {
909                System.err.println("Error: package " + pkg + " not found.");
910                return 1;
911            }
912
913            if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
914                System.err.println("Error: package " + pkg + " does not handle web links.");
915                return 1;
916            }
917
918            if (!mPm.updateIntentVerificationStatus(pkg, newMode, userId)) {
919                System.err.println("Error: unable to update app link status for " + pkg);
920                return 1;
921            }
922        } catch (Exception e) {
923            System.err.println(e.toString());
924            System.err.println(PM_NOT_RUNNING_ERR);
925            return 1;
926        }
927
928        return 0;
929    }
930
931    // pm get-app-link [--user USER_ID] PACKAGE
932    private int runGetAppLink() {
933        int userId = UserHandle.USER_OWNER;
934
935        String opt;
936        while ((opt = nextOption()) != null) {
937            if (opt.equals("--user")) {
938                userId = Integer.parseInt(nextOptionData());
939                if (userId < 0) {
940                    System.err.println("Error: user must be >= 0");
941                    return 1;
942                }
943            } else {
944                System.err.println("Error: unknown option: " + opt);
945                showUsage();
946                return 1;
947            }
948        }
949
950        // Package name to act on; required
951        final String pkg = nextArg();
952        if (pkg == null) {
953            System.err.println("Error: no package specified.");
954            showUsage();
955            return 1;
956        }
957
958        try {
959            final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
960            if (info == null) {
961                System.err.println("Error: package " + pkg + " not found.");
962                return 1;
963            }
964
965            if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
966                System.err.println("Error: package " + pkg + " does not handle web links.");
967                return 1;
968            }
969
970            System.out.println(linkStateToString(mPm.getIntentVerificationStatus(pkg, userId)));
971        } catch (Exception e) {
972            System.err.println(e.toString());
973            System.err.println(PM_NOT_RUNNING_ERR);
974            return 1;
975        }
976
977        return 0;
978    }
979
980    private String linkStateToString(int state) {
981        switch (state) {
982            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
983            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
984            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
985            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
986            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
987        }
988        return "Unknown link state: " + state;
989    }
990
991    private int runSetInstallLocation() {
992        int loc;
993
994        String arg = nextArg();
995        if (arg == null) {
996            System.err.println("Error: no install location specified.");
997            return 1;
998        }
999        try {
1000            loc = Integer.parseInt(arg);
1001        } catch (NumberFormatException e) {
1002            System.err.println("Error: install location has to be a number.");
1003            return 1;
1004        }
1005        try {
1006            if (!mPm.setInstallLocation(loc)) {
1007                System.err.println("Error: install location has to be a number.");
1008                return 1;
1009            }
1010            return 0;
1011        } catch (RemoteException e) {
1012            System.err.println(e.toString());
1013            System.err.println(PM_NOT_RUNNING_ERR);
1014            return 1;
1015        }
1016    }
1017
1018    private int runGetInstallLocation() {
1019        try {
1020            int loc = mPm.getInstallLocation();
1021            String locStr = "invalid";
1022            if (loc == PackageHelper.APP_INSTALL_AUTO) {
1023                locStr = "auto";
1024            } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
1025                locStr = "internal";
1026            } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
1027                locStr = "external";
1028            }
1029            System.out.println(loc + "[" + locStr + "]");
1030            return 0;
1031        } catch (RemoteException e) {
1032            System.err.println(e.toString());
1033            System.err.println(PM_NOT_RUNNING_ERR);
1034            return 1;
1035        }
1036    }
1037
1038    private int runInstall() {
1039        int installFlags = 0;
1040        int userId = UserHandle.USER_ALL;
1041        String installerPackageName = null;
1042
1043        String opt;
1044
1045        String originatingUriString = null;
1046        String referrer = null;
1047        String abi = null;
1048
1049        while ((opt=nextOption()) != null) {
1050            if (opt.equals("-l")) {
1051                installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
1052            } else if (opt.equals("-r")) {
1053                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1054            } else if (opt.equals("-i")) {
1055                installerPackageName = nextOptionData();
1056                if (installerPackageName == null) {
1057                    System.err.println("Error: no value specified for -i");
1058                    return 1;
1059                }
1060            } else if (opt.equals("-t")) {
1061                installFlags |= PackageManager.INSTALL_ALLOW_TEST;
1062            } else if (opt.equals("-s")) {
1063                // Override if -s option is specified.
1064                installFlags |= PackageManager.INSTALL_EXTERNAL;
1065            } else if (opt.equals("-f")) {
1066                // Override if -s option is specified.
1067                installFlags |= PackageManager.INSTALL_INTERNAL;
1068            } else if (opt.equals("-d")) {
1069                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1070            } else if (opt.equals("-g")) {
1071                installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1072            } else if (opt.equals("--originating-uri")) {
1073                originatingUriString = nextOptionData();
1074                if (originatingUriString == null) {
1075                    System.err.println("Error: must supply argument for --originating-uri");
1076                    return 1;
1077                }
1078            } else if (opt.equals("--referrer")) {
1079                referrer = nextOptionData();
1080                if (referrer == null) {
1081                    System.err.println("Error: must supply argument for --referrer");
1082                    return 1;
1083                }
1084            } else if (opt.equals("--abi")) {
1085                abi = checkAbiArgument(nextOptionData());
1086            } else if (opt.equals("--user")) {
1087                userId = Integer.parseInt(nextOptionData());
1088            } else {
1089                System.err.println("Error: Unknown option: " + opt);
1090                return 1;
1091            }
1092        }
1093
1094        if (userId == UserHandle.USER_ALL) {
1095            userId = UserHandle.USER_OWNER;
1096            installFlags |= PackageManager.INSTALL_ALL_USERS;
1097        }
1098
1099        final Uri verificationURI;
1100        final Uri originatingURI;
1101        final Uri referrerURI;
1102
1103        if (originatingUriString != null) {
1104            originatingURI = Uri.parse(originatingUriString);
1105        } else {
1106            originatingURI = null;
1107        }
1108
1109        if (referrer != null) {
1110            referrerURI = Uri.parse(referrer);
1111        } else {
1112            referrerURI = null;
1113        }
1114
1115        // Populate apkURI, must be present
1116        final String apkFilePath = nextArg();
1117        System.err.println("\tpkg: " + apkFilePath);
1118        if (apkFilePath == null) {
1119            System.err.println("Error: no package specified");
1120            return 1;
1121        }
1122
1123        // Populate verificationURI, optionally present
1124        final String verificationFilePath = nextArg();
1125        if (verificationFilePath != null) {
1126            System.err.println("\tver: " + verificationFilePath);
1127            verificationURI = Uri.fromFile(new File(verificationFilePath));
1128        } else {
1129            verificationURI = null;
1130        }
1131
1132        LocalPackageInstallObserver obs = new LocalPackageInstallObserver();
1133        try {
1134            VerificationParams verificationParams = new VerificationParams(verificationURI,
1135                    originatingURI, referrerURI, VerificationParams.NO_UID, null);
1136
1137            mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags,
1138                    installerPackageName, verificationParams, abi, userId);
1139
1140            synchronized (obs) {
1141                while (!obs.finished) {
1142                    try {
1143                        obs.wait();
1144                    } catch (InterruptedException e) {
1145                    }
1146                }
1147                if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
1148                    System.out.println("Success");
1149                    return 0;
1150                } else {
1151                    System.err.println("Failure ["
1152                            + installFailureToString(obs)
1153                            + "]");
1154                    return 1;
1155                }
1156            }
1157        } catch (RemoteException e) {
1158            System.err.println(e.toString());
1159            System.err.println(PM_NOT_RUNNING_ERR);
1160            return 1;
1161        }
1162    }
1163
1164    private int runInstallCreate() throws RemoteException {
1165        int userId = UserHandle.USER_ALL;
1166        String installerPackageName = null;
1167
1168        final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1169
1170        String opt;
1171        while ((opt = nextOption()) != null) {
1172            if (opt.equals("-l")) {
1173                params.installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
1174            } else if (opt.equals("-r")) {
1175                params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
1176            } else if (opt.equals("-i")) {
1177                installerPackageName = nextArg();
1178                if (installerPackageName == null) {
1179                    throw new IllegalArgumentException("Missing installer package");
1180                }
1181            } else if (opt.equals("-t")) {
1182                params.installFlags |= PackageManager.INSTALL_ALLOW_TEST;
1183            } else if (opt.equals("-s")) {
1184                params.installFlags |= PackageManager.INSTALL_EXTERNAL;
1185            } else if (opt.equals("-f")) {
1186                params.installFlags |= PackageManager.INSTALL_INTERNAL;
1187            } else if (opt.equals("-d")) {
1188                params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
1189            } else if (opt.equals("-g")) {
1190                params.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
1191            } else if (opt.equals("--originating-uri")) {
1192                params.originatingUri = Uri.parse(nextOptionData());
1193            } else if (opt.equals("--referrer")) {
1194                params.referrerUri = Uri.parse(nextOptionData());
1195            } else if (opt.equals("-p")) {
1196                params.mode = SessionParams.MODE_INHERIT_EXISTING;
1197                params.appPackageName = nextOptionData();
1198                if (params.appPackageName == null) {
1199                    throw new IllegalArgumentException("Missing inherit package name");
1200                }
1201            } else if (opt.equals("-S")) {
1202                params.setSize(Long.parseLong(nextOptionData()));
1203            } else if (opt.equals("--abi")) {
1204                params.abiOverride = checkAbiArgument(nextOptionData());
1205            } else if (opt.equals("--user")) {
1206                userId = Integer.parseInt(nextOptionData());
1207            } else if (opt.equals("--install-location")) {
1208                params.installLocation = Integer.parseInt(nextOptionData());
1209            } else if (opt.equals("--force-uuid")) {
1210                params.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;
1211                params.volumeUuid = nextOptionData();
1212                if ("internal".equals(params.volumeUuid)) {
1213                    params.volumeUuid = null;
1214                }
1215            } else {
1216                throw new IllegalArgumentException("Unknown option " + opt);
1217            }
1218        }
1219
1220        if (userId == UserHandle.USER_ALL) {
1221            userId = UserHandle.USER_OWNER;
1222            params.installFlags |= PackageManager.INSTALL_ALL_USERS;
1223        }
1224
1225        final int sessionId = mInstaller.createSession(params, installerPackageName, userId);
1226
1227        // NOTE: adb depends on parsing this string
1228        System.out.println("Success: created install session [" + sessionId + "]");
1229        return 0;
1230    }
1231
1232    private int runInstallWrite() throws IOException, RemoteException {
1233        long sizeBytes = -1;
1234
1235        String opt;
1236        while ((opt = nextOption()) != null) {
1237            if (opt.equals("-S")) {
1238                sizeBytes = Long.parseLong(nextOptionData());
1239            } else {
1240                throw new IllegalArgumentException("Unknown option: " + opt);
1241            }
1242        }
1243
1244        final int sessionId = Integer.parseInt(nextArg());
1245        final String splitName = nextArg();
1246
1247        String path = nextArg();
1248        if ("-".equals(path)) {
1249            path = null;
1250        } else if (path != null) {
1251            final File file = new File(path);
1252            if (file.isFile()) {
1253                sizeBytes = file.length();
1254            }
1255        }
1256
1257        final SessionInfo info = mInstaller.getSessionInfo(sessionId);
1258
1259        PackageInstaller.Session session = null;
1260        InputStream in = null;
1261        OutputStream out = null;
1262        try {
1263            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
1264
1265            if (path != null) {
1266                in = new FileInputStream(path);
1267            } else {
1268                in = new SizedInputStream(System.in, sizeBytes);
1269            }
1270            out = session.openWrite(splitName, 0, sizeBytes);
1271
1272            int total = 0;
1273            byte[] buffer = new byte[65536];
1274            int c;
1275            while ((c = in.read(buffer)) != -1) {
1276                total += c;
1277                out.write(buffer, 0, c);
1278
1279                if (info.sizeBytes > 0) {
1280                    final float fraction = ((float) c / (float) info.sizeBytes);
1281                    session.addProgress(fraction);
1282                }
1283            }
1284            session.fsync(out);
1285
1286            System.out.println("Success: streamed " + total + " bytes");
1287            return 0;
1288        } finally {
1289            IoUtils.closeQuietly(out);
1290            IoUtils.closeQuietly(in);
1291            IoUtils.closeQuietly(session);
1292        }
1293    }
1294
1295    private int runInstallCommit() throws RemoteException {
1296        final int sessionId = Integer.parseInt(nextArg());
1297
1298        PackageInstaller.Session session = null;
1299        try {
1300            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
1301
1302            final LocalIntentReceiver receiver = new LocalIntentReceiver();
1303            session.commit(receiver.getIntentSender());
1304
1305            final Intent result = receiver.getResult();
1306            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1307                    PackageInstaller.STATUS_FAILURE);
1308            if (status == PackageInstaller.STATUS_SUCCESS) {
1309                System.out.println("Success");
1310                return 0;
1311            } else {
1312                Log.e(TAG, "Failure details: " + result.getExtras());
1313                System.err.println("Failure ["
1314                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1315                return 1;
1316            }
1317        } finally {
1318            IoUtils.closeQuietly(session);
1319        }
1320    }
1321
1322    private int runInstallAbandon() throws RemoteException {
1323        final int sessionId = Integer.parseInt(nextArg());
1324
1325        PackageInstaller.Session session = null;
1326        try {
1327            session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
1328            session.abandon();
1329            System.out.println("Success");
1330            return 0;
1331        } finally {
1332            IoUtils.closeQuietly(session);
1333        }
1334    }
1335
1336    private int runSetInstaller() throws RemoteException {
1337        final String targetPackage = nextArg();
1338        final String installerPackageName = nextArg();
1339
1340        if (targetPackage == null || installerPackageName == null) {
1341            throw new IllegalArgumentException(
1342                    "must provide both target and installer package names");
1343        }
1344
1345        mPm.setInstallerPackageName(targetPackage, installerPackageName);
1346        System.out.println("Success");
1347        return 0;
1348    }
1349
1350    public int runCreateUser() {
1351        String name;
1352        int userId = -1;
1353        int flags = 0;
1354        String opt;
1355        while ((opt = nextOption()) != null) {
1356            if ("--profileOf".equals(opt)) {
1357                String optionData = nextOptionData();
1358                if (optionData == null || !isNumber(optionData)) {
1359                    System.err.println("Error: no USER_ID specified");
1360                    showUsage();
1361                    return 1;
1362                } else {
1363                    userId = Integer.parseInt(optionData);
1364                }
1365            } else if ("--managed".equals(opt)) {
1366                flags |= UserInfo.FLAG_MANAGED_PROFILE;
1367            } else {
1368                System.err.println("Error: unknown option " + opt);
1369                showUsage();
1370                return 1;
1371            }
1372        }
1373        String arg = nextArg();
1374        if (arg == null) {
1375            System.err.println("Error: no user name specified.");
1376            return 1;
1377        }
1378        name = arg;
1379        try {
1380            UserInfo info = null;
1381            if (userId < 0) {
1382                info = mUm.createUser(name, flags);
1383            } else {
1384                info = mUm.createProfileForUser(name, flags, userId);
1385            }
1386            if (info != null) {
1387                System.out.println("Success: created user id " + info.id);
1388                return 1;
1389            } else {
1390                System.err.println("Error: couldn't create User.");
1391                return 1;
1392            }
1393        } catch (RemoteException e) {
1394            System.err.println(e.toString());
1395            System.err.println(PM_NOT_RUNNING_ERR);
1396            return 1;
1397        }
1398    }
1399
1400    public int runRemoveUser() {
1401        int userId;
1402        String arg = nextArg();
1403        if (arg == null) {
1404            System.err.println("Error: no user id specified.");
1405            return 1;
1406        }
1407        try {
1408            userId = Integer.parseInt(arg);
1409        } catch (NumberFormatException e) {
1410            System.err.println("Error: user id '" + arg + "' is not a number.");
1411            return 1;
1412        }
1413        try {
1414            if (mUm.removeUser(userId)) {
1415                System.out.println("Success: removed user");
1416                return 0;
1417            } else {
1418                System.err.println("Error: couldn't remove user id " + userId);
1419                return 1;
1420            }
1421        } catch (RemoteException e) {
1422            System.err.println(e.toString());
1423            System.err.println(PM_NOT_RUNNING_ERR);
1424            return 1;
1425        }
1426    }
1427
1428    public int runListUsers() {
1429        try {
1430            IActivityManager am = ActivityManagerNative.getDefault();
1431
1432            List<UserInfo> users = mUm.getUsers(false);
1433            if (users == null) {
1434                System.err.println("Error: couldn't get users");
1435                return 1;
1436            } else {
1437                System.out.println("Users:");
1438                for (int i = 0; i < users.size(); i++) {
1439                    String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
1440                    System.out.println("\t" + users.get(i).toString() + running);
1441                }
1442                return 0;
1443            }
1444        } catch (RemoteException e) {
1445            System.err.println(e.toString());
1446            System.err.println(PM_NOT_RUNNING_ERR);
1447            return 1;
1448        }
1449    }
1450
1451    public int runGetMaxUsers() {
1452        System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
1453        return 0;
1454    }
1455
1456    public int runForceDexOpt() {
1457        final String packageName = nextArg();
1458        try {
1459            mPm.forceDexOpt(packageName);
1460            return 0;
1461        } catch (RemoteException e) {
1462            throw e.rethrowAsRuntimeException();
1463        }
1464    }
1465
1466    public int runMovePackage() {
1467        final String packageName = nextArg();
1468        String volumeUuid = nextArg();
1469        if ("internal".equals(volumeUuid)) {
1470            volumeUuid = null;
1471        }
1472
1473        try {
1474            final int moveId = mPm.movePackage(packageName, volumeUuid);
1475
1476            int status = mPm.getMoveStatus(moveId);
1477            while (!PackageManager.isMoveStatusFinished(status)) {
1478                SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1479                status = mPm.getMoveStatus(moveId);
1480            }
1481
1482            if (status == PackageManager.MOVE_SUCCEEDED) {
1483                System.out.println("Success");
1484                return 0;
1485            } else {
1486                System.err.println("Failure [" + status + "]");
1487                return 1;
1488            }
1489        } catch (RemoteException e) {
1490            throw e.rethrowAsRuntimeException();
1491        }
1492    }
1493
1494    public int runMovePrimaryStorage() {
1495        String volumeUuid = nextArg();
1496        if ("internal".equals(volumeUuid)) {
1497            volumeUuid = null;
1498        }
1499
1500        try {
1501            final int moveId = mPm.movePrimaryStorage(volumeUuid);
1502
1503            int status = mPm.getMoveStatus(moveId);
1504            while (!PackageManager.isMoveStatusFinished(status)) {
1505                SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
1506                status = mPm.getMoveStatus(moveId);
1507            }
1508
1509            if (status == PackageManager.MOVE_SUCCEEDED) {
1510                System.out.println("Success");
1511                return 0;
1512            } else {
1513                System.err.println("Failure [" + status + "]");
1514                return 1;
1515            }
1516        } catch (RemoteException e) {
1517            throw e.rethrowAsRuntimeException();
1518        }
1519    }
1520
1521    private int runUninstall() throws RemoteException {
1522        int flags = 0;
1523        int userId = UserHandle.USER_ALL;
1524
1525        String opt;
1526        while ((opt=nextOption()) != null) {
1527            if (opt.equals("-k")) {
1528                flags |= PackageManager.DELETE_KEEP_DATA;
1529            } else if (opt.equals("--user")) {
1530                String param = nextArg();
1531                if (isNumber(param)) {
1532                    userId = Integer.parseInt(param);
1533                } else {
1534                    showUsage();
1535                    System.err.println("Error: Invalid user: " + param);
1536                    return 1;
1537                }
1538            } else {
1539                System.err.println("Error: Unknown option: " + opt);
1540                return 1;
1541            }
1542        }
1543
1544        String pkg = nextArg();
1545        if (pkg == null) {
1546            System.err.println("Error: no package specified");
1547            showUsage();
1548            return 1;
1549        }
1550
1551        if (userId == UserHandle.USER_ALL) {
1552            userId = UserHandle.USER_OWNER;
1553            flags |= PackageManager.DELETE_ALL_USERS;
1554        } else {
1555            PackageInfo info;
1556            try {
1557                info = mPm.getPackageInfo(pkg, 0, userId);
1558            } catch (RemoteException e) {
1559                System.err.println(e.toString());
1560                System.err.println(PM_NOT_RUNNING_ERR);
1561                return 1;
1562            }
1563            if (info == null) {
1564                System.err.println("Failure - not installed for " + userId);
1565                return 1;
1566            }
1567            final boolean isSystem =
1568                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
1569            // If we are being asked to delete a system app for just one
1570            // user set flag so it disables rather than reverting to system
1571            // version of the app.
1572            if (isSystem) {
1573                flags |= PackageManager.DELETE_SYSTEM_APP;
1574            }
1575        }
1576
1577        final LocalIntentReceiver receiver = new LocalIntentReceiver();
1578        mInstaller.uninstall(pkg, null /* callerPackageName */, flags,
1579                receiver.getIntentSender(), userId);
1580
1581        final Intent result = receiver.getResult();
1582        final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
1583                PackageInstaller.STATUS_FAILURE);
1584        if (status == PackageInstaller.STATUS_SUCCESS) {
1585            System.out.println("Success");
1586            return 0;
1587        } else {
1588            Log.e(TAG, "Failure details: " + result.getExtras());
1589            System.err.println("Failure ["
1590                    + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
1591            return 1;
1592        }
1593    }
1594
1595    static class ClearDataObserver extends IPackageDataObserver.Stub {
1596        boolean finished;
1597        boolean result;
1598
1599        @Override
1600        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1601            synchronized (this) {
1602                finished = true;
1603                result = succeeded;
1604                notifyAll();
1605            }
1606        }
1607    }
1608
1609    private int runClear() {
1610        int userId = 0;
1611        String option = nextOption();
1612        if (option != null && option.equals("--user")) {
1613            String optionData = nextOptionData();
1614            if (optionData == null || !isNumber(optionData)) {
1615                System.err.println("Error: no USER_ID specified");
1616                showUsage();
1617                return 1;
1618            } else {
1619                userId = Integer.parseInt(optionData);
1620            }
1621        }
1622
1623        String pkg = nextArg();
1624        if (pkg == null) {
1625            System.err.println("Error: no package specified");
1626            showUsage();
1627            return 1;
1628        }
1629
1630        ClearDataObserver obs = new ClearDataObserver();
1631        try {
1632            ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId);
1633            synchronized (obs) {
1634                while (!obs.finished) {
1635                    try {
1636                        obs.wait();
1637                    } catch (InterruptedException e) {
1638                    }
1639                }
1640            }
1641
1642            if (obs.result) {
1643                System.out.println("Success");
1644                return 0;
1645            } else {
1646                System.err.println("Failed");
1647                return 1;
1648            }
1649        } catch (RemoteException e) {
1650            System.err.println(e.toString());
1651            System.err.println(PM_NOT_RUNNING_ERR);
1652            return 1;
1653        }
1654    }
1655
1656    private static String enabledSettingToString(int state) {
1657        switch (state) {
1658            case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1659                return "default";
1660            case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1661                return "enabled";
1662            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1663                return "disabled";
1664            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1665                return "disabled-user";
1666            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1667                return "disabled-until-used";
1668        }
1669        return "unknown";
1670    }
1671
1672    private static boolean isNumber(String s) {
1673        try {
1674            Integer.parseInt(s);
1675        } catch (NumberFormatException nfe) {
1676            return false;
1677        }
1678        return true;
1679    }
1680
1681    private int runSetEnabledSetting(int state) {
1682        int userId = 0;
1683        String option = nextOption();
1684        if (option != null && option.equals("--user")) {
1685            String optionData = nextOptionData();
1686            if (optionData == null || !isNumber(optionData)) {
1687                System.err.println("Error: no USER_ID specified");
1688                showUsage();
1689                return 1;
1690            } else {
1691                userId = Integer.parseInt(optionData);
1692            }
1693        }
1694
1695        String pkg = nextArg();
1696        if (pkg == null) {
1697            System.err.println("Error: no package or component specified");
1698            showUsage();
1699            return 1;
1700        }
1701        ComponentName cn = ComponentName.unflattenFromString(pkg);
1702        if (cn == null) {
1703            try {
1704                mPm.setApplicationEnabledSetting(pkg, state, 0, userId,
1705                        "shell:" + android.os.Process.myUid());
1706                System.out.println("Package " + pkg + " new state: "
1707                        + enabledSettingToString(
1708                        mPm.getApplicationEnabledSetting(pkg, userId)));
1709                return 0;
1710            } catch (RemoteException e) {
1711                System.err.println(e.toString());
1712                System.err.println(PM_NOT_RUNNING_ERR);
1713                return 1;
1714            }
1715        } else {
1716            try {
1717                mPm.setComponentEnabledSetting(cn, state, 0, userId);
1718                System.out.println("Component " + cn.toShortString() + " new state: "
1719                        + enabledSettingToString(
1720                        mPm.getComponentEnabledSetting(cn, userId)));
1721                return 0;
1722            } catch (RemoteException e) {
1723                System.err.println(e.toString());
1724                System.err.println(PM_NOT_RUNNING_ERR);
1725                return 1;
1726            }
1727        }
1728    }
1729
1730    private int runSetHiddenSetting(boolean state) {
1731        int userId = 0;
1732        String option = nextOption();
1733        if (option != null && option.equals("--user")) {
1734            String optionData = nextOptionData();
1735            if (optionData == null || !isNumber(optionData)) {
1736                System.err.println("Error: no USER_ID specified");
1737                showUsage();
1738                return 1;
1739            } else {
1740                userId = Integer.parseInt(optionData);
1741            }
1742        }
1743
1744        String pkg = nextArg();
1745        if (pkg == null) {
1746            System.err.println("Error: no package or component specified");
1747            showUsage();
1748            return 1;
1749        }
1750        try {
1751            mPm.setApplicationHiddenSettingAsUser(pkg, state, userId);
1752            System.out.println("Package " + pkg + " new hidden state: "
1753                    + mPm.getApplicationHiddenSettingAsUser(pkg, userId));
1754            return 0;
1755        } catch (RemoteException e) {
1756            System.err.println(e.toString());
1757            System.err.println(PM_NOT_RUNNING_ERR);
1758            return 1;
1759        }
1760    }
1761
1762    private int runGrantRevokePermission(boolean grant) {
1763        int userId = UserHandle.USER_OWNER;
1764
1765        String opt = null;
1766        while ((opt = nextOption()) != null) {
1767            if (opt.equals("--user")) {
1768                userId = Integer.parseInt(nextArg());
1769            }
1770        }
1771
1772        String pkg = nextArg();
1773        if (pkg == null) {
1774            System.err.println("Error: no package specified");
1775            showUsage();
1776            return 1;
1777        }
1778        String perm = nextArg();
1779        if (perm == null) {
1780            System.err.println("Error: no permission specified");
1781            showUsage();
1782            return 1;
1783        }
1784
1785        try {
1786            if (grant) {
1787                mPm.grantRuntimePermission(pkg, perm, userId);
1788            } else {
1789                mPm.revokeRuntimePermission(pkg, perm, userId);
1790            }
1791            return 0;
1792        } catch (RemoteException e) {
1793            System.err.println(e.toString());
1794            System.err.println(PM_NOT_RUNNING_ERR);
1795            return 1;
1796        } catch (IllegalArgumentException e) {
1797            System.err.println("Bad argument: " + e.toString());
1798            showUsage();
1799            return 1;
1800        } catch (SecurityException e) {
1801            System.err.println("Operation not allowed: " + e.toString());
1802            return 1;
1803        }
1804    }
1805
1806    private int runResetPermissions() {
1807        try {
1808            mPm.resetRuntimePermissions();
1809            return 0;
1810        } catch (RemoteException e) {
1811            System.err.println(e.toString());
1812            System.err.println(PM_NOT_RUNNING_ERR);
1813            return 1;
1814        } catch (IllegalArgumentException e) {
1815            System.err.println("Bad argument: " + e.toString());
1816            showUsage();
1817            return 1;
1818        } catch (SecurityException e) {
1819            System.err.println("Operation not allowed: " + e.toString());
1820            return 1;
1821        }
1822    }
1823
1824    private int runSetPermissionEnforced() {
1825        final String permission = nextArg();
1826        if (permission == null) {
1827            System.err.println("Error: no permission specified");
1828            showUsage();
1829            return 1;
1830        }
1831        final String enforcedRaw = nextArg();
1832        if (enforcedRaw == null) {
1833            System.err.println("Error: no enforcement specified");
1834            showUsage();
1835            return 1;
1836        }
1837        final boolean enforced = Boolean.parseBoolean(enforcedRaw);
1838        try {
1839            mPm.setPermissionEnforced(permission, enforced);
1840            return 0;
1841        } catch (RemoteException e) {
1842            System.err.println(e.toString());
1843            System.err.println(PM_NOT_RUNNING_ERR);
1844            return 1;
1845        } catch (IllegalArgumentException e) {
1846            System.err.println("Bad argument: " + e.toString());
1847            showUsage();
1848            return 1;
1849        } catch (SecurityException e) {
1850            System.err.println("Operation not allowed: " + e.toString());
1851            return 1;
1852        }
1853    }
1854
1855    static class ClearCacheObserver extends IPackageDataObserver.Stub {
1856        boolean finished;
1857        boolean result;
1858
1859        @Override
1860        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
1861            synchronized (this) {
1862                finished = true;
1863                result = succeeded;
1864                notifyAll();
1865            }
1866        }
1867
1868    }
1869
1870    private int runTrimCaches() {
1871        String size = nextArg();
1872        if (size == null) {
1873            System.err.println("Error: no size specified");
1874            showUsage();
1875            return 1;
1876        }
1877        int len = size.length();
1878        long multiplier = 1;
1879        if (len > 1) {
1880            char c = size.charAt(len-1);
1881            if (c == 'K' || c == 'k') {
1882                multiplier = 1024L;
1883            } else if (c == 'M' || c == 'm') {
1884                multiplier = 1024L*1024L;
1885            } else if (c == 'G' || c == 'g') {
1886                multiplier = 1024L*1024L*1024L;
1887            } else {
1888                System.err.println("Invalid suffix: " + c);
1889                showUsage();
1890                return 1;
1891            }
1892            size = size.substring(0, len-1);
1893        }
1894        long sizeVal;
1895        try {
1896            sizeVal = Long.parseLong(size) * multiplier;
1897        } catch (NumberFormatException e) {
1898            System.err.println("Error: expected number at: " + size);
1899            showUsage();
1900            return 1;
1901        }
1902        String volumeUuid = nextArg();
1903        if ("internal".equals(volumeUuid)) {
1904            volumeUuid = null;
1905        }
1906        ClearDataObserver obs = new ClearDataObserver();
1907        try {
1908            mPm.freeStorageAndNotify(volumeUuid, sizeVal, obs);
1909            synchronized (obs) {
1910                while (!obs.finished) {
1911                    try {
1912                        obs.wait();
1913                    } catch (InterruptedException e) {
1914                    }
1915                }
1916            }
1917            return 0;
1918        } catch (RemoteException e) {
1919            System.err.println(e.toString());
1920            System.err.println(PM_NOT_RUNNING_ERR);
1921            return 1;
1922        } catch (IllegalArgumentException e) {
1923            System.err.println("Bad argument: " + e.toString());
1924            showUsage();
1925            return 1;
1926        } catch (SecurityException e) {
1927            System.err.println("Operation not allowed: " + e.toString());
1928            return 1;
1929        }
1930    }
1931
1932    /**
1933     * Displays the package file for a package.
1934     * @param pckg
1935     */
1936    private int displayPackageFilePath(String pckg) {
1937        try {
1938            PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
1939            if (info != null && info.applicationInfo != null) {
1940                System.out.print("package:");
1941                System.out.println(info.applicationInfo.sourceDir);
1942                if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) {
1943                    for (String splitSourceDir : info.applicationInfo.splitSourceDirs) {
1944                        System.out.print("package:");
1945                        System.out.println(splitSourceDir);
1946                    }
1947                }
1948                return 0;
1949            }
1950        } catch (RemoteException e) {
1951            System.err.println(e.toString());
1952            System.err.println(PM_NOT_RUNNING_ERR);
1953        }
1954        return 1;
1955    }
1956
1957    private Resources getResources(PackageItemInfo pii) {
1958        Resources res = mResourceCache.get(pii.packageName);
1959        if (res != null) return res;
1960
1961        try {
1962            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0);
1963            AssetManager am = new AssetManager();
1964            am.addAssetPath(ai.publicSourceDir);
1965            res = new Resources(am, null, null);
1966            mResourceCache.put(pii.packageName, res);
1967            return res;
1968        } catch (RemoteException e) {
1969            System.err.println(e.toString());
1970            System.err.println(PM_NOT_RUNNING_ERR);
1971            return null;
1972        }
1973    }
1974
1975    private static String checkAbiArgument(String abi) {
1976        if (TextUtils.isEmpty(abi)) {
1977            throw new IllegalArgumentException("Missing ABI argument");
1978        }
1979
1980        if ("-".equals(abi)) {
1981            return abi;
1982        }
1983
1984        final String[] supportedAbis = Build.SUPPORTED_ABIS;
1985        for (String supportedAbi : supportedAbis) {
1986            if (supportedAbi.equals(abi)) {
1987                return abi;
1988            }
1989        }
1990
1991        throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
1992    }
1993
1994    private static class LocalIntentReceiver {
1995        private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>();
1996
1997        private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
1998            @Override
1999            public int send(int code, Intent intent, String resolvedType,
2000                    IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
2001                try {
2002                    mResult.offer(intent, 5, TimeUnit.SECONDS);
2003                } catch (InterruptedException e) {
2004                    throw new RuntimeException(e);
2005                }
2006                return 0;
2007            }
2008        };
2009
2010        public IntentSender getIntentSender() {
2011            return new IntentSender((IIntentSender) mLocalSender);
2012        }
2013
2014        public Intent getResult() {
2015            try {
2016                return mResult.take();
2017            } catch (InterruptedException e) {
2018                throw new RuntimeException(e);
2019            }
2020        }
2021    }
2022
2023    private String nextOption() {
2024        if (mNextArg >= mArgs.length) {
2025            return null;
2026        }
2027        String arg = mArgs[mNextArg];
2028        if (!arg.startsWith("-")) {
2029            return null;
2030        }
2031        mNextArg++;
2032        if (arg.equals("--")) {
2033            return null;
2034        }
2035        if (arg.length() > 1 && arg.charAt(1) != '-') {
2036            if (arg.length() > 2) {
2037                mCurArgData = arg.substring(2);
2038                return arg.substring(0, 2);
2039            } else {
2040                mCurArgData = null;
2041                return arg;
2042            }
2043        }
2044        mCurArgData = null;
2045        return arg;
2046    }
2047
2048    private String nextOptionData() {
2049        if (mCurArgData != null) {
2050            return mCurArgData;
2051        }
2052        if (mNextArg >= mArgs.length) {
2053            return null;
2054        }
2055        String data = mArgs[mNextArg];
2056        mNextArg++;
2057        return data;
2058    }
2059
2060    private String nextArg() {
2061        if (mNextArg >= mArgs.length) {
2062            return null;
2063        }
2064        String arg = mArgs[mNextArg];
2065        mNextArg++;
2066        return arg;
2067    }
2068
2069    private static int showUsage() {
2070        System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
2071        System.err.println("       pm list permission-groups");
2072        System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
2073        System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
2074        System.err.println("       pm list features");
2075        System.err.println("       pm list libraries");
2076        System.err.println("       pm list users");
2077        System.err.println("       pm path PACKAGE");
2078        System.err.println("       pm dump PACKAGE");
2079        System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
2080        System.err.println("       pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
2081        System.err.println("               [--install-location 0/1/2]");
2082        System.err.println("               [--force-uuid internal|UUID]");
2083        System.err.println("       pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
2084        System.err.println("       pm install-commit SESSION_ID");
2085        System.err.println("       pm install-abandon SESSION_ID");
2086        System.err.println("       pm uninstall [-k] [--user USER_ID] PACKAGE");
2087        System.err.println("       pm set-installer PACKAGE INSTALLER");
2088        System.err.println("       pm move-package PACKAGE [internal|UUID]");
2089        System.err.println("       pm move-primary-storage [internal|UUID]");
2090        System.err.println("       pm clear [--user USER_ID] PACKAGE");
2091        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
2092        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
2093        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
2094        System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
2095        System.err.println("       pm hide [--user USER_ID] PACKAGE_OR_COMPONENT");
2096        System.err.println("       pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
2097        System.err.println("       pm grant [--user USER_ID] PACKAGE PERMISSION");
2098        System.err.println("       pm revoke [--user USER_ID] PACKAGE PERMISSION");
2099        System.err.println("       pm reset-permissions");
2100        System.err.println("       pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
2101        System.err.println("       pm get-app-link [--user USER_ID] PACKAGE");
2102        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
2103        System.err.println("       pm get-install-location");
2104        System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
2105        System.err.println("       pm trim-caches DESIRED_FREE_SPACE [internal|UUID]");
2106        System.err.println("       pm create-user [--profileOf USER_ID] [--managed] USER_NAME");
2107        System.err.println("       pm remove-user USER_ID");
2108        System.err.println("       pm get-max-users");
2109        System.err.println("");
2110        System.err.println("pm list packages: prints all packages, optionally only");
2111        System.err.println("  those whose package name contains the text in FILTER.  Options:");
2112        System.err.println("    -f: see their associated file.");
2113        System.err.println("    -d: filter to only show disbled packages.");
2114        System.err.println("    -e: filter to only show enabled packages.");
2115        System.err.println("    -s: filter to only show system packages.");
2116        System.err.println("    -3: filter to only show third party packages.");
2117        System.err.println("    -i: see the installer for the packages.");
2118        System.err.println("    -u: also include uninstalled packages.");
2119        System.err.println("");
2120        System.err.println("pm list permission-groups: prints all known permission groups.");
2121        System.err.println("");
2122        System.err.println("pm list permissions: prints all known permissions, optionally only");
2123        System.err.println("  those in GROUP.  Options:");
2124        System.err.println("    -g: organize by group.");
2125        System.err.println("    -f: print all information.");
2126        System.err.println("    -s: short summary.");
2127        System.err.println("    -d: only list dangerous permissions.");
2128        System.err.println("    -u: list only the permissions users will see.");
2129        System.err.println("");
2130        System.err.println("pm list instrumentation: use to list all test packages; optionally");
2131        System.err.println("  supply <TARGET-PACKAGE> to list the test packages for a particular");
2132        System.err.println("  application.  Options:");
2133        System.err.println("    -f: list the .apk file for the test package.");
2134        System.err.println("");
2135        System.err.println("pm list features: prints all features of the system.");
2136        System.err.println("");
2137        System.err.println("pm list users: prints all users on the system.");
2138        System.err.println("");
2139        System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
2140        System.err.println("");
2141        System.err.println("pm dump: print system state associated with the given PACKAGE.");
2142        System.err.println("");
2143        System.err.println("pm install: install a single legacy package");
2144        System.err.println("pm install-create: create an install session");
2145        System.err.println("    -l: forward lock application");
2146        System.err.println("    -r: replace existing application");
2147        System.err.println("    -t: allow test packages");
2148        System.err.println("    -i: specify the installer package name");
2149        System.err.println("    -s: install application on sdcard");
2150        System.err.println("    -f: install application on internal flash");
2151        System.err.println("    -d: allow version code downgrade");
2152        System.err.println("    -p: partial application install");
2153        System.err.println("    -g: grant all runtime permissions");
2154        System.err.println("    -S: size in bytes of entire session");
2155        System.err.println("");
2156        System.err.println("pm install-write: write a package into existing session; path may");
2157        System.err.println("  be '-' to read from stdin");
2158        System.err.println("    -S: size in bytes of package, required for stdin");
2159        System.err.println("");
2160        System.err.println("pm install-commit: perform install of fully staged session");
2161        System.err.println("pm install-abandon: abandon session");
2162        System.err.println("");
2163        System.err.println("pm set-installer: set installer package name");
2164        System.err.println("");
2165        System.err.println("pm uninstall: removes a package from the system. Options:");
2166        System.err.println("    -k: keep the data and cache directories around after package removal.");
2167        System.err.println("");
2168        System.err.println("pm clear: deletes all data associated with a package.");
2169        System.err.println("");
2170        System.err.println("pm enable, disable, disable-user, disable-until-used: these commands");
2171        System.err.println("  change the enabled state of a given package or component (written");
2172        System.err.println("  as \"package/class\").");
2173        System.err.println("");
2174        System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
2175        System.err.println("    to apps. The permissions must be declared as used in the app's");
2176        System.err.println("    manifest, be runtime permissions (protection level dangerous),");
2177        System.err.println("    and the app targeting SDK greater than Lollipop MR1.");
2178        System.err.println("");
2179        System.err.println("pm reset-permissions: revert all runtime permissions to their default state.");
2180        System.err.println("");
2181        System.err.println("pm get-install-location: returns the current install location.");
2182        System.err.println("    0 [auto]: Let system decide the best location");
2183        System.err.println("    1 [internal]: Install on internal device storage");
2184        System.err.println("    2 [external]: Install on external media");
2185        System.err.println("");
2186        System.err.println("pm set-install-location: changes the default install location.");
2187        System.err.println("  NOTE: this is only intended for debugging; using this can cause");
2188        System.err.println("  applications to break and other undersireable behavior.");
2189        System.err.println("    0 [auto]: Let system decide the best location");
2190        System.err.println("    1 [internal]: Install on internal device storage");
2191        System.err.println("    2 [external]: Install on external media");
2192        System.err.println("");
2193        System.err.println("pm trim-caches: trim cache files to reach the given free space.");
2194        System.err.println("");
2195        System.err.println("pm create-user: create a new user with the given USER_NAME,");
2196        System.err.println("  printing the new user identifier of the user.");
2197        System.err.println("");
2198        System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
2199        System.err.println("  deleting all data associated with that user");
2200        System.err.println("");
2201        return 1;
2202    }
2203}
2204