Pm.java revision e4a5951925f16f18dae91ed65567e96528f17fee
1b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson/*
2b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Copyright (C) 2007 The Android Open Source Project
3b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *
4b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Licensed under the Apache License, Version 2.0 (the "License");
5b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * you may not use this file except in compliance with the License.
6b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * You may obtain a copy of the License at
7b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *
8b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *      http://www.apache.org/licenses/LICENSE-2.0
9b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson *
10b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Unless required by applicable law or agreed to in writing, software
11b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * distributed under the License is distributed on an "AS IS" BASIS,
12b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * See the License for the specific language governing permissions and
14b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * limitations under the License.
15b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson */
16b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
17b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonpackage com.android.commands.pm;
18b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
199730f15ebbf4b64cd48e0777850e56cb516a9ed4Hugo Hudsonimport com.android.internal.content.PackageHelper;
209730f15ebbf4b64cd48e0777850e56cb516a9ed4Hugo Hudson
21b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.ComponentName;
22b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.ApplicationInfo;
23b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.FeatureInfo;
240bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudsonimport android.content.pm.IPackageDeleteObserver;
25b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.IPackageInstallObserver;
26b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.IPackageManager;
27b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.InstrumentationInfo;
28b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.PackageInfo;
29b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.PackageItemInfo;
30b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.PackageManager;
31b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.PermissionGroupInfo;
32b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.pm.PermissionInfo;
33b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.res.AssetManager;
34b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.content.res.Resources;
35b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.net.Uri;
36b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.os.RemoteException;
37b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.os.ServiceManager;
38b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport android.provider.Settings;
39b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
40b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.io.File;
41b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.lang.reflect.Field;
42b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.lang.reflect.Modifier;
43b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.util.ArrayList;
44b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.util.Collections;
45b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.util.Comparator;
46b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.util.List;
47b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonimport java.util.WeakHashMap;
48b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
49b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonpublic final class Pm {
500bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson    IPackageManager mPm;
510bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson
52b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private WeakHashMap<String, Resources> mResourceCache
53b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            = new WeakHashMap<String, Resources>();
54b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
55b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private String[] mArgs;
56b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private int mNextArg;
57b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private String mCurArgData;
58b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
59b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private static final String PM_NOT_RUNNING_ERR =
60b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        "Error: Could not access the Package Manager.  Is the system running?";
61b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
62b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    public static void main(String[] args) {
63b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        new Pm().run(args);
64b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    }
65b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
66b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    public void run(String[] args) {
67dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda        boolean validCommand = false;
68b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if (args.length < 1) {
69b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            showUsage();
709730f15ebbf4b64cd48e0777850e56cb516a9ed4Hugo Hudson            return;
71b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
72b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
73b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
74b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if (mPm == null) {
75b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(PM_NOT_RUNNING_ERR);
76b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
77b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
78b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
79b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        mArgs = args;
80b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        String op = args[0];
81b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        mNextArg = 1;
82b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
83b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("list".equals(op)) {
84b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runList();
85b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
86b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
87b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
88b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("path".equals(op)) {
89b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runPath();
90b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
91b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
92b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
93b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("install".equals(op)) {
94b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runInstall();
95b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
96b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
97b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
98b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("uninstall".equals(op)) {
990bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson            runUninstall();
100b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
101b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
102b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
103b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("enable".equals(op)) {
104b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
105b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
106b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
107b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
108b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("disable".equals(op)) {
109b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
110b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
111b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
112b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
113b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("setInstallLocation".equals(op)) {
114b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runSetInstallLocation();
115b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
116b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
117b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
118b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("getInstallLocation".equals(op)) {
119b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runGetInstallLocation();
120b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
121b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
122b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
123b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
124b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            if (args.length == 1) {
125b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (args[0].equalsIgnoreCase("-l")) {
126b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    validCommand = true;
127b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    runListPackages(false);
128b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (args[0].equalsIgnoreCase("-lf")){
129b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    validCommand = true;
130b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    runListPackages(true);
131b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
132b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            } else if (args.length == 2) {
133b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (args[0].equalsIgnoreCase("-p")) {
134b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    validCommand = true;
135b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    displayPackageFilePath(args[1]);
136b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
137b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
138b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } finally {
139b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            if (validCommand == false) {
140b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (op != null) {
141b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.err.println("Error: unknown command '" + op + "'");
142b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
143b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                showUsage();
144b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
145b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
146b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    }
147b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
148b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    /**
149b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * Execute the list sub-command.
150b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     *
151b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list [package | packages]
152b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list permission-groups
153b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list permissions
154b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list features
155b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list libraries
1569730f15ebbf4b64cd48e0777850e56cb516a9ed4Hugo Hudson     * pm list instrumentation
157b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     */
158b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private void runList() {
159b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        String type = nextArg();
160b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if (type == null) {
161b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println("Error: didn't specify type of data to list");
162b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            showUsage();
163b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
164b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
165b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        if ("package".equals(type) || "packages".equals(type)) {
166b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runListPackages(false);
167b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } else if ("permission-groups".equals(type)) {
168b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runListPermissionGroups();
169b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } else if ("permissions".equals(type)) {
170b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runListPermissions();
171b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } else if ("features".equals(type)) {
172b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runListFeatures();
173b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } else if ("libraries".equals(type)) {
174b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runListLibraries();
175b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } else if ("instrumentation".equals(type)) {
176b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            runListInstrumentation();
177b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } else {
178b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println("Error: unknown list type '" + type + "'");
179b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            showUsage();
180b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
181b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    }
182b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
183b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    /**
184b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * Lists all the installed packages.
185b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     */
186b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private void runListPackages(boolean showApplicationPackage) {
187b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        int getFlags = 0;
188b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        boolean listDisabled = false, listEnabled = false;
189b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
190b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            String opt;
191b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            while ((opt=nextOption()) != null) {
192b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (opt.equals("-l")) {
193b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    // old compat
194b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (opt.equals("-lf")) {
195b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    showApplicationPackage = true;
196b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (opt.equals("-f")) {
197b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    showApplicationPackage = true;
198b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (opt.equals("-d")) {
199b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    listDisabled = true;
200b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (opt.equals("-e")) {
201b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    listEnabled = true;
202b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (opt.equals("-u")) {
203b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
204b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else {
205b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.err.println("Error: Unknown option: " + opt);
206b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    showUsage();
207b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    return;
208b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
209b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
210b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RuntimeException ex) {
211b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println("Error: " + ex.toString());
212b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            showUsage();
213b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
214b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
215b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
216b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        String filter = nextArg();
217dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda
218b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
219b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            List<PackageInfo> packages = mPm.getInstalledPackages(getFlags);
220b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
221b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            int count = packages.size();
222b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int p = 0 ; p < count ; p++) {
223b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                PackageInfo info = packages.get(p);
224dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda                if (filter != null && !info.packageName.contains(filter)) {
225b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    continue;
226b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
227b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if ((!listDisabled || !info.applicationInfo.enabled) &&
228dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda                        (!listEnabled || info.applicationInfo.enabled)) {
229b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.out.print("package:");
230b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    if (showApplicationPackage) {
231b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                        System.out.print(info.applicationInfo.sourceDir);
232b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                        System.out.print("=");
233b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    }
234b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.out.println(info.packageName);
235b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
236b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
237b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RemoteException e) {
238b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(e.toString());
239b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(PM_NOT_RUNNING_ERR);
240b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
241b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    }
242b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
243b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    /**
244b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * Lists all of the features supported by the current device.
245b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     *
246b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list features
247b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     */
248b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private void runListFeatures() {
249b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
250b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            List<FeatureInfo> list = new ArrayList<FeatureInfo>();
251b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
252b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int i=0; i<rawList.length; i++) {
253b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                list.add(rawList[i]);
254b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
255b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
256b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
257b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            // Sort by name
258b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            Collections.sort(list, new Comparator<FeatureInfo>() {
259b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                public int compare(FeatureInfo o1, FeatureInfo o2) {
260b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    if (o1.name == o2.name) return 0;
261b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    if (o1.name == null) return -1;
262b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    if (o2.name == null) return 1;
263b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    return o1.name.compareTo(o2.name);
264b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
265b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            });
266b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
267b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            int count = (list != null) ? list.size() : 0;
268b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int p = 0; p < count; p++) {
269b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                FeatureInfo fi = list.get(p);
270b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print("feature:");
271b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (fi.name != null) System.out.println(fi.name);
272b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                else System.out.println("reqGlEsVersion=0x"
273b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                        + Integer.toHexString(fi.reqGlEsVersion));
274b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
275b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RemoteException e) {
276b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(e.toString());
277b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(PM_NOT_RUNNING_ERR);
278b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
2790bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson    }
280b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
281b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    /**
282b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * Lists all of the libraries supported by the current device.
283b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     *
284b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list libraries
285b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     */
286b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private void runListLibraries() {
287b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
288b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            List<String> list = new ArrayList<String>();
289b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            String[] rawList = mPm.getSystemSharedLibraryNames();
290b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int i=0; i<rawList.length; i++) {
291b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                list.add(rawList[i]);
292b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
293dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda
294dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda
295dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda            // Sort by name
2960bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson            Collections.sort(list, new Comparator<String>() {
2970bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson                public int compare(String o1, String o2) {
2980bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson                    if (o1 == o2) return 0;
2990bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson                    if (o1 == null) return -1;
300b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    if (o2 == null) return 1;
301b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    return o1.compareTo(o2);
302b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
303b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            });
304b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
305b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            int count = (list != null) ? list.size() : 0;
306b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int p = 0; p < count; p++) {
307b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                String lib = list.get(p);
308b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print("library:");
309b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.println(lib);
310b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
311b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RemoteException e) {
312b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(e.toString());
313b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(PM_NOT_RUNNING_ERR);
314b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
3150bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson    }
316b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
317b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    /**
318b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * Lists all of the installed instrumentation, or all for a given package
319b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     *
320b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     * pm list instrumentation [package] [-f]
321b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     */
322b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private void runListInstrumentation() {
323b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        int flags = 0;      // flags != 0 is only used to request meta-data
3240bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson        boolean showPackage = false;
325b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        String targetPackage = null;
326b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
327b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
328b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            String opt;
329b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            while ((opt=nextArg()) != null) {
330b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (opt.equals("-f")) {
331b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    showPackage = true;
332b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else if (opt.charAt(0) != '-') {
333b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    targetPackage = opt;
334b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                } else {
335b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.err.println("Error: Unknown option: " + opt);
336b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    showUsage();
337b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    return;
338b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
339b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
340b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RuntimeException ex) {
341b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println("Error: " + ex.toString());
342b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            showUsage();
343b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            return;
344b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
345b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
346b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
347b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
348b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
3499730f15ebbf4b64cd48e0777850e56cb516a9ed4Hugo Hudson            // Sort by target package
350b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            Collections.sort(list, new Comparator<InstrumentationInfo>() {
351b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
352b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    return o1.targetPackage.compareTo(o2.targetPackage);
353b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
354b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            });
355b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
356b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            int count = (list != null) ? list.size() : 0;
357b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int p = 0; p < count; p++) {
358b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                InstrumentationInfo ii = list.get(p);
359b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print("instrumentation:");
360b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                if (showPackage) {
361b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.out.print(ii.sourceDir);
362b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                    System.out.print("=");
363b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                }
364b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                ComponentName cn = new ComponentName(ii.packageName, ii.name);
365b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print(cn.flattenToShortString());
366b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print(" (target=");
367b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print(ii.targetPackage);
368b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.println(")");
369b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
370b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RemoteException e) {
371b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(e.toString());
3720bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson            System.err.println(PM_NOT_RUNNING_ERR);
373b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
374b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    }
375b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
3760bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson    /**
3770bd6ec5bc06b869131ee0facf38ff02f81f65c10Hugo Hudson     * Lists all the known permission groups.
378b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson     */
379b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private void runListPermissionGroups() {
380b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        try {
381b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
382b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
383b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            int count = pgs.size();
384b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            for (int p = 0 ; p < count ; p++) {
385b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                PermissionGroupInfo pgi = pgs.get(p);
386b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.print("permission group:");
387b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson                System.out.println(pgi.name);
388b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            }
389b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        } catch (RemoteException e) {
390b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(e.toString());
391b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson            System.err.println(PM_NOT_RUNNING_ERR);
392b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        }
393b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    }
394b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson
395b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson    private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
396dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda        if (nonLocalized != null) {
397dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda            return nonLocalized.toString();
398dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda        }
399dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda        Resources r = getResources(pii);
400dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda        if (r != null) {
401dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda            return r.getString(res);
402dc442b4d99512bf7c41ee5ceae6c93a3c3568b57Flavio Lerda        }
403b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson        return null;
404    }
405
406    /**
407     * Lists all the permissions in a group.
408     */
409    private void runListPermissions() {
410        try {
411            boolean labels = false;
412            boolean groups = false;
413            boolean userOnly = false;
414            boolean summary = false;
415            boolean dangerousOnly = false;
416            String opt;
417            while ((opt=nextOption()) != null) {
418                if (opt.equals("-f")) {
419                    labels = true;
420                } else if (opt.equals("-g")) {
421                    groups = true;
422                } else if (opt.equals("-s")) {
423                    groups = true;
424                    labels = true;
425                    summary = true;
426                } else if (opt.equals("-u")) {
427                    userOnly = true;
428                } else if (opt.equals("-d")) {
429                    dangerousOnly = true;
430                } else {
431                    System.err.println("Error: Unknown option: " + opt);
432                    showUsage();
433                    return;
434                }
435            }
436
437            String grp = nextOption();
438            ArrayList<String> groupList = new ArrayList<String>();
439            if (groups) {
440                List<PermissionGroupInfo> infos =
441                        mPm.getAllPermissionGroups(0);
442                for (int i=0; i<infos.size(); i++) {
443                    groupList.add(infos.get(i).name);
444                }
445                groupList.add(null);
446            } else {
447                groupList.add(grp);
448            }
449
450            if (dangerousOnly) {
451                System.out.println("Dangerous Permissions:");
452                System.out.println("");
453                doListPermissions(groupList, groups, labels, summary,
454                        PermissionInfo.PROTECTION_DANGEROUS,
455                        PermissionInfo.PROTECTION_DANGEROUS);
456                if (userOnly) {
457                    System.out.println("Normal Permissions:");
458                    System.out.println("");
459                    doListPermissions(groupList, groups, labels, summary,
460                            PermissionInfo.PROTECTION_NORMAL,
461                            PermissionInfo.PROTECTION_NORMAL);
462                }
463            } else if (userOnly) {
464                System.out.println("Dangerous and Normal Permissions:");
465                System.out.println("");
466                doListPermissions(groupList, groups, labels, summary,
467                        PermissionInfo.PROTECTION_NORMAL,
468                        PermissionInfo.PROTECTION_DANGEROUS);
469            } else {
470                System.out.println("All Permissions:");
471                System.out.println("");
472                doListPermissions(groupList, groups, labels, summary,
473                        -10000, 10000);
474            }
475        } catch (RemoteException e) {
476            System.err.println(e.toString());
477            System.err.println(PM_NOT_RUNNING_ERR);
478        }
479    }
480
481    private void doListPermissions(ArrayList<String> groupList,
482            boolean groups, boolean labels, boolean summary,
483            int startProtectionLevel, int endProtectionLevel)
484            throws RemoteException {
485        for (int i=0; i<groupList.size(); i++) {
486            String groupName = groupList.get(i);
487            String prefix = "";
488            if (groups) {
489                if (i > 0) System.out.println("");
490                if (groupName != null) {
491                    PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
492                            groupName, 0);
493                    if (summary) {
494                        Resources res = getResources(pgi);
495                        if (res != null) {
496                            System.out.print(loadText(pgi, pgi.labelRes,
497                                    pgi.nonLocalizedLabel) + ": ");
498                        } else {
499                            System.out.print(pgi.name + ": ");
500
501                        }
502                    } else {
503                        System.out.println((labels ? "+ " : "")
504                                + "group:" + pgi.name);
505                        if (labels) {
506                            System.out.println("  package:" + pgi.packageName);
507                            Resources res = getResources(pgi);
508                            if (res != null) {
509                                System.out.println("  label:"
510                                        + loadText(pgi, pgi.labelRes,
511                                                pgi.nonLocalizedLabel));
512                                System.out.println("  description:"
513                                        + loadText(pgi, pgi.descriptionRes,
514                                                pgi.nonLocalizedDescription));
515                            }
516                        }
517                    }
518                } else {
519                    System.out.println(((labels && !summary)
520                            ? "+ " : "") + "ungrouped:");
521                }
522                prefix = "  ";
523            }
524            List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
525                    groupList.get(i), 0);
526            int count = ps.size();
527            boolean first = true;
528            for (int p = 0 ; p < count ; p++) {
529                PermissionInfo pi = ps.get(p);
530                if (groups && groupName == null && pi.group != null) {
531                    continue;
532                }
533                if (pi.protectionLevel < startProtectionLevel
534                        || pi.protectionLevel > endProtectionLevel) {
535                    continue;
536                }
537                if (summary) {
538                    if (first) {
539                        first = false;
540                    } else {
541                        System.out.print(", ");
542                    }
543                    Resources res = getResources(pi);
544                    if (res != null) {
545                        System.out.print(loadText(pi, pi.labelRes,
546                                pi.nonLocalizedLabel));
547                    } else {
548                        System.out.print(pi.name);
549                    }
550                } else {
551                    System.out.println(prefix + (labels ? "+ " : "")
552                            + "permission:" + pi.name);
553                    if (labels) {
554                        System.out.println(prefix + "  package:" + pi.packageName);
555                        Resources res = getResources(pi);
556                        if (res != null) {
557                            System.out.println(prefix + "  label:"
558                                    + loadText(pi, pi.labelRes,
559                                            pi.nonLocalizedLabel));
560                            System.out.println(prefix + "  description:"
561                                    + loadText(pi, pi.descriptionRes,
562                                            pi.nonLocalizedDescription));
563                        }
564                        String protLevel = "unknown";
565                        switch(pi.protectionLevel) {
566                            case PermissionInfo.PROTECTION_DANGEROUS:
567                                protLevel = "dangerous";
568                                break;
569                            case PermissionInfo.PROTECTION_NORMAL:
570                                protLevel = "normal";
571                                break;
572                            case PermissionInfo.PROTECTION_SIGNATURE:
573                                protLevel = "signature";
574                                break;
575                            case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
576                                protLevel = "signatureOrSystem";
577                                break;
578                        }
579                        System.out.println(prefix + "  protectionLevel:" + protLevel);
580                    }
581                }
582            }
583
584            if (summary) {
585                System.out.println("");
586            }
587        }
588    }
589
590    private void runPath() {
591        String pkg = nextArg();
592        if (pkg == null) {
593            System.err.println("Error: no package specified");
594            showUsage();
595            return;
596        }
597        displayPackageFilePath(pkg);
598    }
599
600    class PackageInstallObserver extends IPackageInstallObserver.Stub {
601        boolean finished;
602        int result;
603
604        public void packageInstalled(String name, int status) {
605            synchronized( this) {
606                finished = true;
607                result = status;
608                notifyAll();
609            }
610        }
611    }
612
613    /**
614     * Converts a failure code into a string by using reflection to find a matching constant
615     * in PackageManager.
616     */
617    private String installFailureToString(int result) {
618        Field[] fields = PackageManager.class.getFields();
619        for (Field f: fields) {
620            if (f.getType() == int.class) {
621                int modifiers = f.getModifiers();
622                // only look at public final static fields.
623                if (((modifiers & Modifier.FINAL) != 0) &&
624                        ((modifiers & Modifier.PUBLIC) != 0) &&
625                        ((modifiers & Modifier.STATIC) != 0)) {
626                    String fieldName = f.getName();
627                    if (fieldName.startsWith("INSTALL_FAILED_") ||
628                            fieldName.startsWith("INSTALL_PARSE_FAILED_")) {
629                        // get the int value and compare it to result.
630                        try {
631                            if (result == f.getInt(null)) {
632                                return fieldName;
633                            }
634                        } catch (IllegalAccessException e) {
635                            // this shouldn't happen since we only look for public static fields.
636                        }
637                    }
638                }
639            }
640        }
641
642        // couldn't find a matching constant? return the value
643        return Integer.toString(result);
644    }
645
646    private void runSetInstallLocation() {
647        int loc;
648
649        String arg = nextArg();
650        if (arg == null) {
651            System.err.println("Error: no install location specified.");
652            showUsage();
653            return;
654        }
655        try {
656            loc = Integer.parseInt(arg);
657        } catch (NumberFormatException e) {
658            System.err.println("Error: install location has to be a number.");
659            showUsage();
660            return;
661        }
662        try {
663            if (!mPm.setInstallLocation(loc)) {
664                System.err.println("Error: install location has to be a number.");
665                showUsage();
666            }
667        } catch (RemoteException e) {
668            System.err.println(e.toString());
669            System.err.println(PM_NOT_RUNNING_ERR);
670        }
671    }
672
673    private void runGetInstallLocation() {
674        try {
675            int loc = mPm.getInstallLocation();
676            String locStr = "invalid";
677            if (loc == PackageHelper.APP_INSTALL_AUTO) {
678                locStr = "auto";
679            } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
680                locStr = "internal";
681            } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
682                locStr = "external";
683            }
684            System.out.println(loc + "[" + locStr + "]");
685        } catch (RemoteException e) {
686            System.err.println(e.toString());
687            System.err.println(PM_NOT_RUNNING_ERR);
688        }
689    }
690
691    private void runInstall() {
692        int installFlags = 0;
693        String installerPackageName = null;
694
695        String opt;
696        while ((opt=nextOption()) != null) {
697            if (opt.equals("-l")) {
698                installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
699            } else if (opt.equals("-r")) {
700                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
701            } else if (opt.equals("-i")) {
702                installerPackageName = nextOptionData();
703                if (installerPackageName == null) {
704                    System.err.println("Error: no value specified for -i");
705                    showUsage();
706                    return;
707                }
708            } else if (opt.equals("-t")) {
709                installFlags |= PackageManager.INSTALL_ALLOW_TEST;
710            } else if (opt.equals("-s")) {
711                // Override if -s option is specified.
712                installFlags |= PackageManager.INSTALL_EXTERNAL;
713            } else if (opt.equals("-f")) {
714                // Override if -s option is specified.
715                installFlags |= PackageManager.INSTALL_INTERNAL;
716            } else {
717                System.err.println("Error: Unknown option: " + opt);
718                showUsage();
719                return;
720            }
721        }
722
723        String apkFilePath = nextArg();
724        System.err.println("\tpkg: " + apkFilePath);
725        if (apkFilePath == null) {
726            System.err.println("Error: no package specified");
727            showUsage();
728            return;
729        }
730
731        PackageInstallObserver obs = new PackageInstallObserver();
732        try {
733            mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,
734                    installerPackageName);
735
736            synchronized (obs) {
737                while (!obs.finished) {
738                    try {
739                        obs.wait();
740                    } catch (InterruptedException e) {
741                    }
742                }
743                if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
744                    System.out.println("Success");
745                } else {
746                    System.err.println("Failure ["
747                            + installFailureToString(obs.result)
748                            + "]");
749                }
750            }
751        } catch (RemoteException e) {
752            System.err.println(e.toString());
753            System.err.println(PM_NOT_RUNNING_ERR);
754        }
755    }
756
757    class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
758        boolean finished;
759        boolean result;
760
761        public void packageDeleted(boolean succeeded) {
762            synchronized (this) {
763                finished = true;
764                result = succeeded;
765                notifyAll();
766            }
767        }
768    }
769
770    private void runUninstall() {
771        int unInstallFlags = 0;
772
773        String opt = nextOption();
774        if (opt != null && opt.equals("-k")) {
775            unInstallFlags = PackageManager.DONT_DELETE_DATA;
776        }
777
778        String pkg = nextArg();
779        if (pkg == null) {
780            System.err.println("Error: no package specified");
781            showUsage();
782            return;
783        }
784        boolean result = deletePackage(pkg, unInstallFlags);
785        if (result) {
786            System.out.println("Success");
787        } else {
788            System.out.println("Failure");
789        }
790    }
791
792    private boolean deletePackage(String pkg, int unInstallFlags) {
793        PackageDeleteObserver obs = new PackageDeleteObserver();
794        try {
795            mPm.deletePackage(pkg, obs, unInstallFlags);
796
797            synchronized (obs) {
798                while (!obs.finished) {
799                    try {
800                        obs.wait();
801                    } catch (InterruptedException e) {
802                    }
803                }
804            }
805        } catch (RemoteException e) {
806            System.err.println(e.toString());
807            System.err.println(PM_NOT_RUNNING_ERR);
808        }
809        return obs.result;
810    }
811
812    private static String enabledSettingToString(int state) {
813        switch (state) {
814            case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
815                return "default";
816            case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
817                return "enabled";
818            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
819                return "disabled";
820        }
821        return "unknown";
822    }
823
824    private void runSetEnabledSetting(int state) {
825        String pkg = nextArg();
826        if (pkg == null) {
827            System.err.println("Error: no package or component specified");
828            showUsage();
829            return;
830        }
831        ComponentName cn = ComponentName.unflattenFromString(pkg);
832        if (cn == null) {
833            try {
834                mPm.setApplicationEnabledSetting(pkg, state, 0);
835                System.err.println("Package " + pkg + " new state: "
836                        + enabledSettingToString(
837                                mPm.getApplicationEnabledSetting(pkg)));
838            } catch (RemoteException e) {
839                System.err.println(e.toString());
840                System.err.println(PM_NOT_RUNNING_ERR);
841            }
842        } else {
843            try {
844                mPm.setComponentEnabledSetting(cn, state, 0);
845                System.err.println("Component " + cn.toShortString() + " new state: "
846                        + enabledSettingToString(
847                                mPm.getComponentEnabledSetting(cn)));
848            } catch (RemoteException e) {
849                System.err.println(e.toString());
850                System.err.println(PM_NOT_RUNNING_ERR);
851            }
852        }
853    }
854
855    /**
856     * Displays the package file for a package.
857     * @param pckg
858     */
859    private void displayPackageFilePath(String pckg) {
860        try {
861            PackageInfo info = mPm.getPackageInfo(pckg, 0);
862            if (info != null && info.applicationInfo != null) {
863                System.out.print("package:");
864                System.out.println(info.applicationInfo.sourceDir);
865            }
866        } catch (RemoteException e) {
867            System.err.println(e.toString());
868            System.err.println(PM_NOT_RUNNING_ERR);
869        }
870    }
871
872    private Resources getResources(PackageItemInfo pii) {
873        Resources res = mResourceCache.get(pii.packageName);
874        if (res != null) return res;
875
876        try {
877            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0);
878            AssetManager am = new AssetManager();
879            am.addAssetPath(ai.publicSourceDir);
880            res = new Resources(am, null, null);
881            mResourceCache.put(pii.packageName, res);
882            return res;
883        } catch (RemoteException e) {
884            System.err.println(e.toString());
885            System.err.println(PM_NOT_RUNNING_ERR);
886            return null;
887        }
888    }
889
890    private String nextOption() {
891        if (mNextArg >= mArgs.length) {
892            return null;
893        }
894        String arg = mArgs[mNextArg];
895        if (!arg.startsWith("-")) {
896            return null;
897        }
898        mNextArg++;
899        if (arg.equals("--")) {
900            return null;
901        }
902        if (arg.length() > 1 && arg.charAt(1) != '-') {
903            if (arg.length() > 2) {
904                mCurArgData = arg.substring(2);
905                return arg.substring(0, 2);
906            } else {
907                mCurArgData = null;
908                return arg;
909            }
910        }
911        mCurArgData = null;
912        return arg;
913    }
914
915    private String nextOptionData() {
916        if (mCurArgData != null) {
917            return mCurArgData;
918        }
919        if (mNextArg >= mArgs.length) {
920            return null;
921        }
922        String data = mArgs[mNextArg];
923        mNextArg++;
924        return data;
925    }
926
927    private String nextArg() {
928        if (mNextArg >= mArgs.length) {
929            return null;
930        }
931        String arg = mArgs[mNextArg];
932        mNextArg++;
933        return arg;
934    }
935
936    private static void showUsage() {
937        System.err.println("usage: pm [list|path|install|uninstall]");
938        System.err.println("       pm list packages [-f] [-d] [-e] [-u] [FILTER]");
939        System.err.println("       pm list permission-groups");
940        System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
941        System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
942        System.err.println("       pm list features");
943        System.err.println("       pm list libraries");
944        System.err.println("       pm path PACKAGE");
945        System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
946        System.err.println("       pm uninstall [-k] PACKAGE");
947        System.err.println("       pm enable PACKAGE_OR_COMPONENT");
948        System.err.println("       pm disable PACKAGE_OR_COMPONENT");
949        System.err.println("       pm setInstallLocation [0/auto] [1/internal] [2/external]");
950        System.err.println("");
951        System.err.println("The list packages command prints all packages, optionally only");
952        System.err.println("those whose package name contains the text in FILTER.  Options:");
953        System.err.println("  -f: see their associated file.");
954        System.err.println("  -d: filter to include disbled packages.");
955        System.err.println("  -e: filter to include enabled packages.");
956        System.err.println("  -u: also include uninstalled packages.");
957        System.err.println("");
958        System.err.println("The list permission-groups command prints all known");
959        System.err.println("permission groups.");
960        System.err.println("");
961        System.err.println("The list permissions command prints all known");
962        System.err.println("permissions, optionally only those in GROUP.  Options:");
963        System.err.println("  -g: organize by group.");
964        System.err.println("  -f: print all information.");
965        System.err.println("  -s: short summary.");
966        System.err.println("  -d: only list dangerous permissions.");
967        System.err.println("  -u: list only the permissions users will see.");
968        System.err.println("");
969        System.err.println("The list instrumentation command prints all instrumentations,");
970        System.err.println("or only those that target a specified package.  Options:");
971        System.err.println("  -f: see their associated file.");
972        System.err.println("");
973        System.err.println("The list features command prints all features of the system.");
974        System.err.println("");
975        System.err.println("The path command prints the path to the .apk of a package.");
976        System.err.println("");
977        System.err.println("The install command installs a package to the system.  Options:");
978        System.err.println("  -l: install the package with FORWARD_LOCK.");
979        System.err.println("  -r: reinstall an exisiting app, keeping its data.");
980        System.err.println("  -t: allow test .apks to be installed.");
981        System.err.println("  -i: specify the installer package name.");
982        System.err.println("  -s: install package on sdcard.");
983        System.err.println("  -f: install package on internal flash.");
984        System.err.println("");
985        System.err.println("The uninstall command removes a package from the system. Options:");
986        System.err.println("  -k: keep the data and cache directories around.");
987        System.err.println("after the package removal.");
988        System.err.println("");
989        System.err.println("The enable and disable commands change the enabled state of");
990        System.err.println("a given package or component (written as \"package/class\").");
991        System.err.println("");
992        System.err.println("The getInstallLocation command gets the current install location");
993        System.err.println("  0 [auto]: Let system decide the best location");
994        System.err.println("  1 [internal]: Install on internal device storage");
995        System.err.println("  2 [external]: Install on external media");
996        System.err.println("");
997        System.err.println("The setInstallLocation command changes the default install location");
998        System.err.println("  0 [auto]: Let system decide the best location");
999        System.err.println("  1 [internal]: Install on internal device storage");
1000        System.err.println("  2 [external]: Install on external media");
1001    }
1002}
1003