blob: ff16c6e340b35faab8a5a5230c9e91c0ac9b85b0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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.content.ComponentName;
20import android.content.pm.ApplicationInfo;
Dianne Hackborn039c68e2009-09-26 16:39:23 -070021import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.pm.IPackageDeleteObserver;
23import android.content.pm.IPackageInstallObserver;
24import android.content.pm.IPackageManager;
25import android.content.pm.InstrumentationInfo;
26import android.content.pm.PackageInfo;
27import android.content.pm.PackageItemInfo;
28import android.content.pm.PackageManager;
29import android.content.pm.PermissionGroupInfo;
30import android.content.pm.PermissionInfo;
31import android.content.res.AssetManager;
32import android.content.res.Resources;
33import android.net.Uri;
34import android.os.RemoteException;
35import android.os.ServiceManager;
36
37import java.io.File;
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070038import java.lang.reflect.Field;
39import java.lang.reflect.Modifier;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import java.util.ArrayList;
41import java.util.Collections;
42import java.util.Comparator;
43import java.util.List;
44import java.util.WeakHashMap;
45
46public final class Pm {
47 IPackageManager mPm;
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 private WeakHashMap<String, Resources> mResourceCache
50 = new WeakHashMap<String, Resources>();
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 private String[] mArgs;
53 private int mNextArg;
54 private String mCurArgData;
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070055
56 private static final String PM_NOT_RUNNING_ERR =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 "Error: Could not access the Package Manager. Is the system running?";
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 public static void main(String[] args) {
60 new Pm().run(args);
61 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 public void run(String[] args) {
64 boolean validCommand = false;
65 if (args.length < 1) {
66 showUsage();
67 return;
68 }
69
70 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
71 if (mPm == null) {
72 System.err.println(PM_NOT_RUNNING_ERR);
73 return;
74 }
75
76 mArgs = args;
77 String op = args[0];
78 mNextArg = 1;
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 if ("list".equals(op)) {
81 runList();
82 return;
83 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 if ("path".equals(op)) {
86 runPath();
87 return;
88 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 if ("install".equals(op)) {
91 runInstall();
92 return;
93 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -070094
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080095 if ("mountsd".equals(op)) {
96 runMountSd();
97 return;
98 }
99
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 if ("uninstall".equals(op)) {
101 runUninstall();
102 return;
103 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 if ("enable".equals(op)) {
106 runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
107 return;
108 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 if ("disable".equals(op)) {
111 runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
112 return;
113 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 try {
116 if (args.length == 1) {
117 if (args[0].equalsIgnoreCase("-l")) {
118 validCommand = true;
119 runListPackages(false);
120 } else if (args[0].equalsIgnoreCase("-lf")){
121 validCommand = true;
122 runListPackages(true);
123 }
124 } else if (args.length == 2) {
125 if (args[0].equalsIgnoreCase("-p")) {
126 validCommand = true;
127 displayPackageFilePath(args[1]);
128 }
129 }
130 } finally {
131 if (validCommand == false) {
132 if (op != null) {
133 System.err.println("Error: unknown command '" + op + "'");
134 }
135 showUsage();
136 }
137 }
138 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 /**
141 * Execute the list sub-command.
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700142 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 * pm list [package | packages]
144 * pm list permission-groups
145 * pm list permissions
Dianne Hackborn039c68e2009-09-26 16:39:23 -0700146 * pm list features
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 * pm list instrumentation
148 */
149 private void runList() {
150 String type = nextArg();
151 if (type == null) {
152 System.err.println("Error: didn't specify type of data to list");
153 showUsage();
154 return;
155 }
156 if ("package".equals(type) || "packages".equals(type)) {
157 runListPackages(false);
158 } else if ("permission-groups".equals(type)) {
159 runListPermissionGroups();
160 } else if ("permissions".equals(type)) {
161 runListPermissions();
Dianne Hackborn039c68e2009-09-26 16:39:23 -0700162 } else if ("features".equals(type)) {
163 runListFeatures();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 } else if ("instrumentation".equals(type)) {
165 runListInstrumentation();
166 } else {
167 System.err.println("Error: unknown list type '" + type + "'");
168 showUsage();
169 }
170 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 /**
173 * Lists all the installed packages.
174 */
175 private void runListPackages(boolean showApplicationPackage) {
176 try {
177 String opt;
178 while ((opt=nextOption()) != null) {
179 if (opt.equals("-l")) {
180 // old compat
181 } else if (opt.equals("-lf")) {
182 showApplicationPackage = true;
183 } else if (opt.equals("-f")) {
184 showApplicationPackage = true;
185 } else {
186 System.err.println("Error: Unknown option: " + opt);
187 showUsage();
188 return;
189 }
190 }
191 } catch (RuntimeException ex) {
192 System.err.println("Error: " + ex.toString());
193 showUsage();
194 return;
195 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 try {
198 List<PackageInfo> packages = mPm.getInstalledPackages(0 /* all */);
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 int count = packages.size();
201 for (int p = 0 ; p < count ; p++) {
202 PackageInfo info = packages.get(p);
203 System.out.print("package:");
204 if (showApplicationPackage) {
205 System.out.print(info.applicationInfo.sourceDir);
206 System.out.print("=");
207 }
208 System.out.println(info.packageName);
209 }
210 } catch (RemoteException e) {
211 System.err.println(e.toString());
212 System.err.println(PM_NOT_RUNNING_ERR);
213 }
214 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 /**
Dianne Hackborn039c68e2009-09-26 16:39:23 -0700217 * Lists all of the features supported by the current device.
218 *
219 * pm list features
220 */
221 private void runListFeatures() {
222 try {
223 List<FeatureInfo> list = new ArrayList<FeatureInfo>();
224 FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
225 for (int i=0; i<rawList.length; i++) {
226 list.add(rawList[i]);
227 }
228
229
230 // Sort by name
231 Collections.sort(list, new Comparator<FeatureInfo>() {
232 public int compare(FeatureInfo o1, FeatureInfo o2) {
233 if (o1.name == o2.name) return 0;
234 if (o1.name == null) return -1;
235 if (o2.name == null) return 1;
236 return o1.name.compareTo(o2.name);
237 }
238 });
239
240 int count = (list != null) ? list.size() : 0;
241 for (int p = 0; p < count; p++) {
242 FeatureInfo fi = list.get(p);
243 System.out.print("feature:");
244 if (fi.name != null) System.out.println(fi.name);
245 else System.out.println("reqGlEsVersion=0x"
246 + Integer.toHexString(fi.reqGlEsVersion));
247 }
248 } catch (RemoteException e) {
249 System.err.println(e.toString());
250 System.err.println(PM_NOT_RUNNING_ERR);
251 }
252 }
253
254 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 * Lists all of the installed instrumentation, or all for a given package
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700256 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 * pm list instrumentation [package] [-f]
258 */
259 private void runListInstrumentation() {
260 int flags = 0; // flags != 0 is only used to request meta-data
261 boolean showPackage = false;
262 String targetPackage = null;
263
264 try {
265 String opt;
266 while ((opt=nextArg()) != null) {
267 if (opt.equals("-f")) {
268 showPackage = true;
269 } else if (opt.charAt(0) != '-') {
270 targetPackage = opt;
271 } else {
272 System.err.println("Error: Unknown option: " + opt);
273 showUsage();
274 return;
275 }
276 }
277 } catch (RuntimeException ex) {
278 System.err.println("Error: " + ex.toString());
279 showUsage();
280 return;
281 }
282
283 try {
284 List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
285
286 // Sort by target package
287 Collections.sort(list, new Comparator<InstrumentationInfo>() {
288 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
289 return o1.targetPackage.compareTo(o2.targetPackage);
290 }
291 });
292
293 int count = (list != null) ? list.size() : 0;
294 for (int p = 0; p < count; p++) {
295 InstrumentationInfo ii = list.get(p);
296 System.out.print("instrumentation:");
297 if (showPackage) {
298 System.out.print(ii.sourceDir);
299 System.out.print("=");
300 }
301 ComponentName cn = new ComponentName(ii.packageName, ii.name);
302 System.out.print(cn.flattenToShortString());
303 System.out.print(" (target=");
304 System.out.print(ii.targetPackage);
305 System.out.println(")");
306 }
307 } catch (RemoteException e) {
308 System.err.println(e.toString());
309 System.err.println(PM_NOT_RUNNING_ERR);
310 }
311 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 /**
314 * Lists all the known permission groups.
315 */
316 private void runListPermissionGroups() {
317 try {
318 List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 int count = pgs.size();
321 for (int p = 0 ; p < count ; p++) {
322 PermissionGroupInfo pgi = pgs.get(p);
323 System.out.print("permission group:");
324 System.out.println(pgi.name);
325 }
326 } catch (RemoteException e) {
327 System.err.println(e.toString());
328 System.err.println(PM_NOT_RUNNING_ERR);
329 }
330 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
333 if (nonLocalized != null) {
334 return nonLocalized.toString();
335 }
336 Resources r = getResources(pii);
337 if (r != null) {
338 return r.getString(res);
339 }
340 return null;
341 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 /**
344 * Lists all the permissions in a group.
345 */
346 private void runListPermissions() {
347 try {
348 boolean labels = false;
349 boolean groups = false;
350 boolean userOnly = false;
351 boolean summary = false;
352 boolean dangerousOnly = false;
353 String opt;
354 while ((opt=nextOption()) != null) {
355 if (opt.equals("-f")) {
356 labels = true;
357 } else if (opt.equals("-g")) {
358 groups = true;
359 } else if (opt.equals("-s")) {
360 groups = true;
361 labels = true;
362 summary = true;
363 } else if (opt.equals("-u")) {
364 userOnly = true;
365 } else if (opt.equals("-d")) {
366 dangerousOnly = true;
367 } else {
368 System.err.println("Error: Unknown option: " + opt);
369 showUsage();
370 return;
371 }
372 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 String grp = nextOption();
375 ArrayList<String> groupList = new ArrayList<String>();
376 if (groups) {
377 List<PermissionGroupInfo> infos =
378 mPm.getAllPermissionGroups(0);
379 for (int i=0; i<infos.size(); i++) {
380 groupList.add(infos.get(i).name);
381 }
382 groupList.add(null);
383 } else {
384 groupList.add(grp);
385 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 if (dangerousOnly) {
388 System.out.println("Dangerous Permissions:");
389 System.out.println("");
390 doListPermissions(groupList, groups, labels, summary,
391 PermissionInfo.PROTECTION_DANGEROUS,
392 PermissionInfo.PROTECTION_DANGEROUS);
393 if (userOnly) {
394 System.out.println("Normal Permissions:");
395 System.out.println("");
396 doListPermissions(groupList, groups, labels, summary,
397 PermissionInfo.PROTECTION_NORMAL,
398 PermissionInfo.PROTECTION_NORMAL);
399 }
400 } else if (userOnly) {
401 System.out.println("Dangerous and Normal Permissions:");
402 System.out.println("");
403 doListPermissions(groupList, groups, labels, summary,
404 PermissionInfo.PROTECTION_NORMAL,
405 PermissionInfo.PROTECTION_DANGEROUS);
406 } else {
407 System.out.println("All Permissions:");
408 System.out.println("");
409 doListPermissions(groupList, groups, labels, summary,
410 -10000, 10000);
411 }
412 } catch (RemoteException e) {
413 System.err.println(e.toString());
414 System.err.println(PM_NOT_RUNNING_ERR);
415 }
416 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 private void doListPermissions(ArrayList<String> groupList,
419 boolean groups, boolean labels, boolean summary,
420 int startProtectionLevel, int endProtectionLevel)
421 throws RemoteException {
422 for (int i=0; i<groupList.size(); i++) {
423 String groupName = groupList.get(i);
424 String prefix = "";
425 if (groups) {
426 if (i > 0) System.out.println("");
427 if (groupName != null) {
428 PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
429 groupName, 0);
430 if (summary) {
431 Resources res = getResources(pgi);
432 if (res != null) {
433 System.out.print(loadText(pgi, pgi.labelRes,
434 pgi.nonLocalizedLabel) + ": ");
435 } else {
436 System.out.print(pgi.name + ": ");
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 }
439 } else {
440 System.out.println((labels ? "+ " : "")
441 + "group:" + pgi.name);
442 if (labels) {
443 System.out.println(" package:" + pgi.packageName);
444 Resources res = getResources(pgi);
445 if (res != null) {
446 System.out.println(" label:"
447 + loadText(pgi, pgi.labelRes,
448 pgi.nonLocalizedLabel));
449 System.out.println(" description:"
450 + loadText(pgi, pgi.descriptionRes,
451 pgi.nonLocalizedDescription));
452 }
453 }
454 }
455 } else {
456 System.out.println(((labels && !summary)
457 ? "+ " : "") + "ungrouped:");
458 }
459 prefix = " ";
460 }
461 List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
462 groupList.get(i), 0);
463 int count = ps.size();
464 boolean first = true;
465 for (int p = 0 ; p < count ; p++) {
466 PermissionInfo pi = ps.get(p);
467 if (groups && groupName == null && pi.group != null) {
468 continue;
469 }
470 if (pi.protectionLevel < startProtectionLevel
471 || pi.protectionLevel > endProtectionLevel) {
472 continue;
473 }
474 if (summary) {
475 if (first) {
476 first = false;
477 } else {
478 System.out.print(", ");
479 }
480 Resources res = getResources(pi);
481 if (res != null) {
482 System.out.print(loadText(pi, pi.labelRes,
483 pi.nonLocalizedLabel));
484 } else {
485 System.out.print(pi.name);
486 }
487 } else {
488 System.out.println(prefix + (labels ? "+ " : "")
489 + "permission:" + pi.name);
490 if (labels) {
491 System.out.println(prefix + " package:" + pi.packageName);
492 Resources res = getResources(pi);
493 if (res != null) {
494 System.out.println(prefix + " label:"
495 + loadText(pi, pi.labelRes,
496 pi.nonLocalizedLabel));
497 System.out.println(prefix + " description:"
498 + loadText(pi, pi.descriptionRes,
499 pi.nonLocalizedDescription));
500 }
501 String protLevel = "unknown";
502 switch(pi.protectionLevel) {
503 case PermissionInfo.PROTECTION_DANGEROUS:
504 protLevel = "dangerous";
505 break;
506 case PermissionInfo.PROTECTION_NORMAL:
507 protLevel = "normal";
508 break;
509 case PermissionInfo.PROTECTION_SIGNATURE:
510 protLevel = "signature";
511 break;
512 case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
513 protLevel = "signatureOrSystem";
514 break;
515 }
516 System.out.println(prefix + " protectionLevel:" + protLevel);
517 }
518 }
519 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 if (summary) {
522 System.out.println("");
523 }
524 }
525 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 private void runPath() {
528 String pkg = nextArg();
529 if (pkg == null) {
530 System.err.println("Error: no package specified");
531 showUsage();
532 return;
533 }
534 displayPackageFilePath(pkg);
535 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 class PackageInstallObserver extends IPackageInstallObserver.Stub {
538 boolean finished;
539 int result;
540
541 public void packageInstalled(String name, int status) {
542 synchronized( this) {
543 finished = true;
544 result = status;
545 notifyAll();
546 }
547 }
548 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700549
550 /**
551 * Converts a failure code into a string by using reflection to find a matching constant
552 * in PackageManager.
553 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 private String installFailureToString(int result) {
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700555 Field[] fields = PackageManager.class.getFields();
556 for (Field f: fields) {
557 if (f.getType() == int.class) {
558 int modifiers = f.getModifiers();
559 // only look at public final static fields.
560 if (((modifiers & Modifier.FINAL) != 0) &&
561 ((modifiers & Modifier.PUBLIC) != 0) &&
562 ((modifiers & Modifier.STATIC) != 0)) {
563 String fieldName = f.getName();
564 if (fieldName.startsWith("INSTALL_FAILED_") ||
565 fieldName.startsWith("INSTALL_PARSE_FAILED_")) {
566 // get the int value and compare it to result.
567 try {
568 if (result == f.getInt(null)) {
569 return fieldName;
570 }
571 } catch (IllegalAccessException e) {
572 // this shouldn't happen since we only look for public static fields.
573 }
574 }
575 }
576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700578
579 // couldn't find a matching constant? return the value
580 return Integer.toString(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 private void runInstall() {
584 int installFlags = 0;
Jacek Surazskic64322c2009-04-28 15:26:38 +0200585 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586
587 String opt;
588 while ((opt=nextOption()) != null) {
589 if (opt.equals("-l")) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700590 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 } else if (opt.equals("-r")) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700592 installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
Jacek Surazskic64322c2009-04-28 15:26:38 +0200593 } else if (opt.equals("-i")) {
594 installerPackageName = nextOptionData();
595 if (installerPackageName == null) {
596 System.err.println("Error: no value specified for -i");
597 showUsage();
598 return;
599 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700600 } else if (opt.equals("-t")) {
601 installFlags |= PackageManager.INSTALL_ALLOW_TEST;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800602 } else if (opt.equals("-s")) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800603 installFlags |= PackageManager.INSTALL_EXTERNAL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 } else {
605 System.err.println("Error: Unknown option: " + opt);
606 showUsage();
607 return;
608 }
609 }
610
611 String apkFilePath = nextArg();
612 System.err.println("\tpkg: " + apkFilePath);
613 if (apkFilePath == null) {
614 System.err.println("Error: no package specified");
615 showUsage();
616 return;
617 }
618
619 PackageInstallObserver obs = new PackageInstallObserver();
620 try {
Jacek Surazskic64322c2009-04-28 15:26:38 +0200621 mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,
622 installerPackageName);
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 synchronized (obs) {
625 while (!obs.finished) {
626 try {
627 obs.wait();
628 } catch (InterruptedException e) {
629 }
630 }
631 if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
632 System.out.println("Success");
633 } else {
634 System.err.println("Failure ["
635 + installFailureToString(obs.result)
636 + "]");
637 }
638 }
639 } catch (RemoteException e) {
640 System.err.println(e.toString());
641 System.err.println(PM_NOT_RUNNING_ERR);
642 }
643 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700644
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -0800645 private void runMountSd() {
646 String opt;
647 boolean mount = false;
648 while ((opt=nextOption()) != null) {
649 if (opt.equals("-m")) {
650 String mountStr = nextOptionData();
651 if (mountStr == null) {
652 System.err.println("Error: no value specified for -m");
653 showUsage();
654 return;
655 }
656 if ("true".equalsIgnoreCase(mountStr)) {
657 mount = true;
658 } else if ("false".equalsIgnoreCase(mountStr)) {
659 mount = false;
660 } else {
661 System.err.println("Error: no value specified for -m");
662 showUsage();
663 return;
664 }
665 }
666 }
667
668 try {
669 mPm.updateExternalMediaStatus(mount);
670 } catch (RemoteException e) {
671 System.err.println(e.toString());
672 System.err.println(PM_NOT_RUNNING_ERR);
673 }
674 }
675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
677 boolean finished;
678 boolean result;
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 public void packageDeleted(boolean succeeded) {
681 synchronized (this) {
682 finished = true;
683 result = succeeded;
684 notifyAll();
685 }
686 }
687 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 private void runUninstall() {
690 int unInstallFlags = 0;
691
692 String opt = nextOption();
693 if (opt != null && opt.equals("-k")) {
694 unInstallFlags = PackageManager.DONT_DELETE_DATA;
695 }
696
697 String pkg = nextArg();
698 if (pkg == null) {
699 System.err.println("Error: no package specified");
700 showUsage();
701 return;
702 }
703 boolean result = deletePackage(pkg, unInstallFlags);
704 if (result) {
705 System.out.println("Success");
706 } else {
707 System.out.println("Failure");
708 }
709 }
710
711 private boolean deletePackage(String pkg, int unInstallFlags) {
712 PackageDeleteObserver obs = new PackageDeleteObserver();
713 try {
714 mPm.deletePackage(pkg, obs, unInstallFlags);
715
716 synchronized (obs) {
717 while (!obs.finished) {
718 try {
719 obs.wait();
720 } catch (InterruptedException e) {
721 }
722 }
723 }
724 } catch (RemoteException e) {
725 System.err.println(e.toString());
726 System.err.println(PM_NOT_RUNNING_ERR);
727 }
728 return obs.result;
729 }
730
731 private static String enabledSettingToString(int state) {
732 switch (state) {
733 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
734 return "default";
735 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
736 return "enabled";
737 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
738 return "disabled";
739 }
740 return "unknown";
741 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 private void runSetEnabledSetting(int state) {
744 String pkg = nextArg();
745 if (pkg == null) {
746 System.err.println("Error: no package or component specified");
747 showUsage();
748 return;
749 }
750 ComponentName cn = ComponentName.unflattenFromString(pkg);
751 if (cn == null) {
752 try {
753 mPm.setApplicationEnabledSetting(pkg, state, 0);
754 System.err.println("Package " + pkg + " new state: "
755 + enabledSettingToString(
756 mPm.getApplicationEnabledSetting(pkg)));
757 } catch (RemoteException e) {
758 System.err.println(e.toString());
759 System.err.println(PM_NOT_RUNNING_ERR);
760 }
761 } else {
762 try {
763 mPm.setComponentEnabledSetting(cn, state, 0);
764 System.err.println("Component " + cn.toShortString() + " new state: "
765 + enabledSettingToString(
766 mPm.getComponentEnabledSetting(cn)));
767 } catch (RemoteException e) {
768 System.err.println(e.toString());
769 System.err.println(PM_NOT_RUNNING_ERR);
770 }
771 }
772 }
773
774 /**
775 * Displays the package file for a package.
776 * @param pckg
777 */
778 private void displayPackageFilePath(String pckg) {
779 try {
780 PackageInfo info = mPm.getPackageInfo(pckg, 0);
781 if (info != null && info.applicationInfo != null) {
782 System.out.print("package:");
783 System.out.println(info.applicationInfo.sourceDir);
784 }
785 } catch (RemoteException e) {
786 System.err.println(e.toString());
787 System.err.println(PM_NOT_RUNNING_ERR);
788 }
789 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 private Resources getResources(PackageItemInfo pii) {
792 Resources res = mResourceCache.get(pii.packageName);
793 if (res != null) return res;
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 try {
796 ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0);
797 AssetManager am = new AssetManager();
798 am.addAssetPath(ai.publicSourceDir);
799 res = new Resources(am, null, null);
800 mResourceCache.put(pii.packageName, res);
801 return res;
802 } catch (RemoteException e) {
803 System.err.println(e.toString());
804 System.err.println(PM_NOT_RUNNING_ERR);
805 return null;
806 }
807 }
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 private String nextOption() {
810 if (mNextArg >= mArgs.length) {
811 return null;
812 }
813 String arg = mArgs[mNextArg];
814 if (!arg.startsWith("-")) {
815 return null;
816 }
817 mNextArg++;
818 if (arg.equals("--")) {
819 return null;
820 }
821 if (arg.length() > 1 && arg.charAt(1) != '-') {
822 if (arg.length() > 2) {
823 mCurArgData = arg.substring(2);
824 return arg.substring(0, 2);
825 } else {
826 mCurArgData = null;
827 return arg;
828 }
829 }
830 mCurArgData = null;
831 return arg;
832 }
833
834 private String nextOptionData() {
835 if (mCurArgData != null) {
836 return mCurArgData;
837 }
838 if (mNextArg >= mArgs.length) {
839 return null;
840 }
841 String data = mArgs[mNextArg];
842 mNextArg++;
843 return data;
844 }
845
846 private String nextArg() {
847 if (mNextArg >= mArgs.length) {
848 return null;
849 }
850 String arg = mArgs[mNextArg];
851 mNextArg++;
852 return arg;
853 }
854
855 private static void showUsage() {
856 System.err.println("usage: pm [list|path|install|uninstall]");
857 System.err.println(" pm list packages [-f]");
858 System.err.println(" pm list permission-groups");
859 System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
Xavier Ducrohet23b4faf2009-09-24 17:41:13 -0700860 System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]");
Dianne Hackborn039c68e2009-09-26 16:39:23 -0700861 System.err.println(" pm list features");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 System.err.println(" pm path PACKAGE");
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800863 System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] PATH");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 System.err.println(" pm uninstall [-k] PACKAGE");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -0800865 System.err.println(" pm mountsd [-m true/false]");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 System.err.println(" pm enable PACKAGE_OR_COMPONENT");
867 System.err.println(" pm disable PACKAGE_OR_COMPONENT");
868 System.err.println("");
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700869 System.err.println("The list packages command prints all packages. Options:");
870 System.err.println(" -f: see their associated file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 System.err.println("");
872 System.err.println("The list permission-groups command prints all known");
873 System.err.println("permission groups.");
874 System.err.println("");
875 System.err.println("The list permissions command prints all known");
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700876 System.err.println("permissions, optionally only those in GROUP. Options:");
877 System.err.println(" -g: organize by group.");
878 System.err.println(" -f: print all information.");
879 System.err.println(" -s: short summary.");
880 System.err.println(" -d: only list dangerous permissions.");
881 System.err.println(" -u: list only the permissions users will see.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 System.err.println("");
883 System.err.println("The list instrumentation command prints all instrumentations,");
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700884 System.err.println("or only those that target a specified package. Options:");
885 System.err.println(" -f: see their associated file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 System.err.println("");
Dianne Hackborn039c68e2009-09-26 16:39:23 -0700887 System.err.println("The list features command prints all features of the system.");
888 System.err.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 System.err.println("The path command prints the path to the .apk of a package.");
890 System.err.println("");
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700891 System.err.println("The install command installs a package to the system. Options:");
892 System.err.println(" -l: install the package with FORWARD_LOCK.");
893 System.err.println(" -r: reinstall an exisiting app, keeping its data.");
894 System.err.println(" -t: allow test .apks to be installed.");
895 System.err.println(" -i: specify the installer package name.");
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800896 System.err.println(" -s: install package on sdcard.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 System.err.println("");
Dianne Hackbornade3eca2009-05-11 18:54:45 -0700898 System.err.println("The uninstall command removes a package from the system. Options:");
899 System.err.println(" -k: keep the data and cache directories around.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 System.err.println("after the package removal.");
901 System.err.println("");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -0800902 System.err.println("The mountsd command simulates mounting/unmounting sdcard.Options:");
903 System.err.println(" -m: true or false.");
904 System.err.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 System.err.println("The enable and disable commands change the enabled state of");
906 System.err.println("a given package or component (written as \"package/class\").");
907 }
908}