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