blob: bee1530055b6a0d1e45080797551ef3f95337202 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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.server;
18
19import com.android.internal.app.ResolverActivity;
20import com.android.internal.util.FastXmlSerializer;
21import com.android.internal.util.XmlUtils;
22
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25import org.xmlpull.v1.XmlSerializer;
26
27import android.app.ActivityManagerNative;
28import android.app.IActivityManager;
29import android.app.PendingIntent;
30import android.app.PendingIntent.CanceledException;
31import android.content.ComponentName;
32import android.content.ContentResolver;
33import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
36import android.content.pm.ActivityInfo;
37import android.content.pm.ApplicationInfo;
38import android.content.pm.ComponentInfo;
39import android.content.pm.IPackageDataObserver;
40import android.content.pm.IPackageDeleteObserver;
41import android.content.pm.IPackageInstallObserver;
42import android.content.pm.IPackageManager;
43import android.content.pm.IPackageStatsObserver;
44import android.content.pm.InstrumentationInfo;
45import android.content.pm.PackageInfo;
46import android.content.pm.PackageManager;
47import android.content.pm.PackageStats;
48import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
49import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
50import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
51import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
52import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
53import android.content.pm.PackageParser;
54import android.content.pm.PermissionInfo;
55import android.content.pm.PermissionGroupInfo;
56import android.content.pm.ProviderInfo;
57import android.content.pm.ResolveInfo;
58import android.content.pm.ServiceInfo;
59import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.net.Uri;
61import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070062import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.Bundle;
64import android.os.HandlerThread;
65import android.os.Parcel;
66import android.os.RemoteException;
67import android.os.Environment;
68import android.os.FileObserver;
69import android.os.FileUtils;
70import android.os.Handler;
71import android.os.ParcelFileDescriptor;
72import android.os.Process;
73import android.os.ServiceManager;
74import android.os.SystemClock;
75import android.os.SystemProperties;
76import android.util.*;
77import android.view.Display;
78import android.view.WindowManager;
79
80import java.io.File;
81import java.io.FileDescriptor;
82import java.io.FileInputStream;
83import java.io.FileNotFoundException;
84import java.io.FileOutputStream;
85import java.io.FileReader;
86import java.io.FilenameFilter;
87import java.io.IOException;
88import java.io.InputStream;
89import java.io.PrintWriter;
90import java.util.ArrayList;
91import java.util.Arrays;
92import java.util.Collections;
93import java.util.Comparator;
94import java.util.Enumeration;
95import java.util.HashMap;
96import java.util.HashSet;
97import java.util.Iterator;
98import java.util.List;
99import java.util.Map;
100import java.util.Set;
101import java.util.zip.ZipEntry;
102import java.util.zip.ZipFile;
103import java.util.zip.ZipOutputStream;
104
105class PackageManagerService extends IPackageManager.Stub {
106 private static final String TAG = "PackageManager";
107 private static final boolean DEBUG_SETTINGS = false;
108 private static final boolean DEBUG_PREFERRED = false;
109
110 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
111 private static final int RADIO_UID = Process.PHONE_UID;
112 private static final int FIRST_APPLICATION_UID =
113 Process.FIRST_APPLICATION_UID;
114 private static final int MAX_APPLICATION_UIDS = 1000;
115
116 private static final boolean SHOW_INFO = false;
117
118 private static final boolean GET_CERTIFICATES = true;
119
120 private static final int REMOVE_EVENTS =
121 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
122 private static final int ADD_EVENTS =
123 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
124
125 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
126
127 static final int SCAN_MONITOR = 1<<0;
128 static final int SCAN_NO_DEX = 1<<1;
129 static final int SCAN_FORCE_DEX = 1<<2;
130 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
131 static final int SCAN_FORWARD_LOCKED = 1<<4;
The Android Open Source Project10592532009-03-18 17:39:46 -0700132 static final int SCAN_NEW_INSTALL = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134 static final int LOG_BOOT_PROGRESS_PMS_START = 3060;
135 static final int LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START = 3070;
136 static final int LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START = 3080;
137 static final int LOG_BOOT_PROGRESS_PMS_SCAN_END = 3090;
138 static final int LOG_BOOT_PROGRESS_PMS_READY = 3100;
139
140 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
141 Process.THREAD_PRIORITY_BACKGROUND);
142 final Handler mHandler;
143
Dianne Hackborn851a5412009-05-08 12:06:44 -0700144 final int mSdkVersion = Build.VERSION.SDK_INT;
145 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
146 ? null : Build.VERSION.CODENAME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147
148 final Context mContext;
149 final boolean mFactoryTest;
150 final DisplayMetrics mMetrics;
151 final int mDefParseFlags;
152 final String[] mSeparateProcesses;
153
154 // This is where all application persistent data goes.
155 final File mAppDataDir;
156
157 // This is the object monitoring the framework dir.
158 final FileObserver mFrameworkInstallObserver;
159
160 // This is the object monitoring the system app dir.
161 final FileObserver mSystemInstallObserver;
162
163 // This is the object monitoring mAppInstallDir.
164 final FileObserver mAppInstallObserver;
165
166 // This is the object monitoring mDrmAppPrivateInstallDir.
167 final FileObserver mDrmAppInstallObserver;
168
169 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
170 // LOCK HELD. Can be called with mInstallLock held.
171 final Installer mInstaller;
172
173 final File mFrameworkDir;
174 final File mSystemAppDir;
175 final File mAppInstallDir;
176
177 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
178 // apps.
179 final File mDrmAppPrivateInstallDir;
180
181 // ----------------------------------------------------------------
182
183 // Lock for state used when installing and doing other long running
184 // operations. Methods that must be called with this lock held have
185 // the prefix "LI".
186 final Object mInstallLock = new Object();
187
188 // These are the directories in the 3rd party applications installed dir
189 // that we have currently loaded packages from. Keys are the application's
190 // installed zip file (absolute codePath), and values are Package.
191 final HashMap<String, PackageParser.Package> mAppDirs =
192 new HashMap<String, PackageParser.Package>();
193
194 // Information for the parser to write more useful error messages.
195 File mScanningPath;
196 int mLastScanError;
197
198 final int[] mOutPermissions = new int[3];
199
200 // ----------------------------------------------------------------
201
202 // Keys are String (package name), values are Package. This also serves
203 // as the lock for the global state. Methods that must be called with
204 // this lock held have the prefix "LP".
205 final HashMap<String, PackageParser.Package> mPackages =
206 new HashMap<String, PackageParser.Package>();
207
208 final Settings mSettings;
209 boolean mRestoredSettings;
210 boolean mReportedUidError;
211
212 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
213 int[] mGlobalGids;
214
215 // These are the built-in uid -> permission mappings that were read from the
216 // etc/permissions.xml file.
217 final SparseArray<HashSet<String>> mSystemPermissions =
218 new SparseArray<HashSet<String>>();
219
220 // These are the built-in shared libraries that were read from the
221 // etc/permissions.xml file.
222 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
223
224 // All available activities, for your resolving pleasure.
225 final ActivityIntentResolver mActivities =
226 new ActivityIntentResolver();
227
228 // All available receivers, for your resolving pleasure.
229 final ActivityIntentResolver mReceivers =
230 new ActivityIntentResolver();
231
232 // All available services, for your resolving pleasure.
233 final ServiceIntentResolver mServices = new ServiceIntentResolver();
234
235 // Keys are String (provider class name), values are Provider.
236 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
237 new HashMap<ComponentName, PackageParser.Provider>();
238
239 // Mapping from provider base names (first directory in content URI codePath)
240 // to the provider information.
241 final HashMap<String, PackageParser.Provider> mProviders =
242 new HashMap<String, PackageParser.Provider>();
243
244 // Mapping from instrumentation class names to info about them.
245 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
246 new HashMap<ComponentName, PackageParser.Instrumentation>();
247
248 // Mapping from permission names to info about them.
249 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
250 new HashMap<String, PackageParser.PermissionGroup>();
251
252 boolean mSystemReady;
253 boolean mSafeMode;
254 boolean mHasSystemUidErrors;
255
256 ApplicationInfo mAndroidApplication;
257 final ActivityInfo mResolveActivity = new ActivityInfo();
258 final ResolveInfo mResolveInfo = new ResolveInfo();
259 ComponentName mResolveComponentName;
260 PackageParser.Package mPlatformPackage;
261
262 public static final IPackageManager main(Context context, boolean factoryTest) {
263 PackageManagerService m = new PackageManagerService(context, factoryTest);
264 ServiceManager.addService("package", m);
265 return m;
266 }
267
268 static String[] splitString(String str, char sep) {
269 int count = 1;
270 int i = 0;
271 while ((i=str.indexOf(sep, i)) >= 0) {
272 count++;
273 i++;
274 }
275
276 String[] res = new String[count];
277 i=0;
278 count = 0;
279 int lastI=0;
280 while ((i=str.indexOf(sep, i)) >= 0) {
281 res[count] = str.substring(lastI, i);
282 count++;
283 i++;
284 lastI = i;
285 }
286 res[count] = str.substring(lastI, str.length());
287 return res;
288 }
289
290 public PackageManagerService(Context context, boolean factoryTest) {
291 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
292 SystemClock.uptimeMillis());
293
294 if (mSdkVersion <= 0) {
295 Log.w(TAG, "**** ro.build.version.sdk not set!");
296 }
297
298 mContext = context;
299 mFactoryTest = factoryTest;
300 mMetrics = new DisplayMetrics();
301 mSettings = new Settings();
302 mSettings.addSharedUserLP("android.uid.system",
303 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
304 mSettings.addSharedUserLP("android.uid.phone",
305 MULTIPLE_APPLICATION_UIDS
306 ? RADIO_UID : FIRST_APPLICATION_UID,
307 ApplicationInfo.FLAG_SYSTEM);
308
309 String separateProcesses = SystemProperties.get("debug.separate_processes");
310 if (separateProcesses != null && separateProcesses.length() > 0) {
311 if ("*".equals(separateProcesses)) {
312 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
313 mSeparateProcesses = null;
314 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
315 } else {
316 mDefParseFlags = 0;
317 mSeparateProcesses = separateProcesses.split(",");
318 Log.w(TAG, "Running with debug.separate_processes: "
319 + separateProcesses);
320 }
321 } else {
322 mDefParseFlags = 0;
323 mSeparateProcesses = null;
324 }
325
326 Installer installer = new Installer();
327 // Little hacky thing to check if installd is here, to determine
328 // whether we are running on the simulator and thus need to take
329 // care of building the /data file structure ourself.
330 // (apparently the sim now has a working installer)
331 if (installer.ping() && Process.supportsProcesses()) {
332 mInstaller = installer;
333 } else {
334 mInstaller = null;
335 }
336
337 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
338 Display d = wm.getDefaultDisplay();
339 d.getMetrics(mMetrics);
340
341 synchronized (mInstallLock) {
342 synchronized (mPackages) {
343 mHandlerThread.start();
344 mHandler = new Handler(mHandlerThread.getLooper());
345
346 File dataDir = Environment.getDataDirectory();
347 mAppDataDir = new File(dataDir, "data");
348 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
349
350 if (mInstaller == null) {
351 // Make sure these dirs exist, when we are running in
352 // the simulator.
353 // Make a wide-open directory for random misc stuff.
354 File miscDir = new File(dataDir, "misc");
355 miscDir.mkdirs();
356 mAppDataDir.mkdirs();
357 mDrmAppPrivateInstallDir.mkdirs();
358 }
359
360 readPermissions();
361
362 mRestoredSettings = mSettings.readLP();
363 long startTime = SystemClock.uptimeMillis();
364
365 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
366 startTime);
367
368 int scanMode = SCAN_MONITOR;
369
370 final HashSet<String> libFiles = new HashSet<String>();
371
372 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
373
374 if (mInstaller != null) {
375 /**
376 * Out of paranoia, ensure that everything in the boot class
377 * path has been dexed.
378 */
379 String bootClassPath = System.getProperty("java.boot.class.path");
380 if (bootClassPath != null) {
381 String[] paths = splitString(bootClassPath, ':');
382 for (int i=0; i<paths.length; i++) {
383 try {
384 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
385 libFiles.add(paths[i]);
386 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
387 }
388 } catch (FileNotFoundException e) {
389 Log.w(TAG, "Boot class path not found: " + paths[i]);
390 } catch (IOException e) {
391 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
392 }
393 }
394 } else {
395 Log.w(TAG, "No BOOTCLASSPATH found!");
396 }
397
398 /**
399 * Also ensure all external libraries have had dexopt run on them.
400 */
401 if (mSharedLibraries.size() > 0) {
402 Iterator<String> libs = mSharedLibraries.values().iterator();
403 while (libs.hasNext()) {
404 String lib = libs.next();
405 try {
406 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
407 libFiles.add(lib);
408 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
409 }
410 } catch (FileNotFoundException e) {
411 Log.w(TAG, "Library not found: " + lib);
412 } catch (IOException e) {
413 Log.w(TAG, "Exception reading library: " + lib, e);
414 }
415 }
416 }
417
418 // Gross hack for now: we know this file doesn't contain any
419 // code, so don't dexopt it to avoid the resulting log spew.
420 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
421
422 /**
423 * And there are a number of commands implemented in Java, which
424 * we currently need to do the dexopt on so that they can be
425 * run from a non-root shell.
426 */
427 String[] frameworkFiles = mFrameworkDir.list();
428 if (frameworkFiles != null && mInstaller != null) {
429 for (int i=0; i<frameworkFiles.length; i++) {
430 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
431 String path = libPath.getPath();
432 // Skip the file if we alrady did it.
433 if (libFiles.contains(path)) {
434 continue;
435 }
436 // Skip the file if it is not a type we want to dexopt.
437 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
438 continue;
439 }
440 try {
441 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
442 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
443 }
444 } catch (FileNotFoundException e) {
445 Log.w(TAG, "Jar not found: " + path);
446 } catch (IOException e) {
447 Log.w(TAG, "Exception reading jar: " + path, e);
448 }
449 }
450 }
451 }
452
453 mFrameworkInstallObserver = new AppDirObserver(
454 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
455 mFrameworkInstallObserver.startWatching();
456 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
457 scanMode | SCAN_NO_DEX);
458 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
459 mSystemInstallObserver = new AppDirObserver(
460 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
461 mSystemInstallObserver.startWatching();
462 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
463 mAppInstallDir = new File(dataDir, "app");
464 if (mInstaller == null) {
465 // Make sure these dirs exist, when we are running in
466 // the simulator.
467 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
468 }
469 //look for any incomplete package installations
470 ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
471 //clean up list
472 for(int i = 0; i < deletePkgsList.size(); i++) {
473 //clean up here
474 cleanupInstallFailedPackage(deletePkgsList.get(i));
475 }
476 //delete tmp files
477 deleteTempPackageFiles();
478
479 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
480 SystemClock.uptimeMillis());
481 mAppInstallObserver = new AppDirObserver(
482 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
483 mAppInstallObserver.startWatching();
484 scanDirLI(mAppInstallDir, 0, scanMode);
485
486 mDrmAppInstallObserver = new AppDirObserver(
487 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
488 mDrmAppInstallObserver.startWatching();
489 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode);
490
491 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
492 SystemClock.uptimeMillis());
493 Log.i(TAG, "Time to scan packages: "
494 + ((SystemClock.uptimeMillis()-startTime)/1000f)
495 + " seconds");
496
497 updatePermissionsLP();
498
499 mSettings.writeLP();
500
501 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
502 SystemClock.uptimeMillis());
503
504 // Now after opening every single application zip, make sure they
505 // are all flushed. Not really needed, but keeps things nice and
506 // tidy.
507 Runtime.getRuntime().gc();
508 } // synchronized (mPackages)
509 } // synchronized (mInstallLock)
510 }
511
512 @Override
513 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
514 throws RemoteException {
515 try {
516 return super.onTransact(code, data, reply, flags);
517 } catch (RuntimeException e) {
518 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
519 Log.e(TAG, "Package Manager Crash", e);
520 }
521 throw e;
522 }
523 }
524
525 void cleanupInstallFailedPackage(String packageName) {
526 if (mInstaller != null) {
527 int retCode = mInstaller.remove(packageName);
528 if (retCode < 0) {
529 Log.w(TAG, "Couldn't remove app data directory for package: "
530 + packageName + ", retcode=" + retCode);
531 }
532 } else {
533 //for emulator
534 PackageParser.Package pkg = mPackages.get(packageName);
535 File dataDir = new File(pkg.applicationInfo.dataDir);
536 dataDir.delete();
537 }
538 mSettings.removePackageLP(packageName);
539 }
540
541 void readPermissions() {
542 // Read permissions from .../etc/permission directory.
543 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
544 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
545 Log.w(TAG, "No directory " + libraryDir + ", skipping");
546 return;
547 }
548 if (!libraryDir.canRead()) {
549 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
550 return;
551 }
552
553 // Iterate over the files in the directory and scan .xml files
554 for (File f : libraryDir.listFiles()) {
555 // We'll read platform.xml last
556 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
557 continue;
558 }
559
560 if (!f.getPath().endsWith(".xml")) {
561 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
562 continue;
563 }
564 if (!f.canRead()) {
565 Log.w(TAG, "Permissions library file " + f + " cannot be read");
566 continue;
567 }
568
569 readPermissionsFromXml(f);
570 }
571
572 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
573 final File permFile = new File(Environment.getRootDirectory(),
574 "etc/permissions/platform.xml");
575 readPermissionsFromXml(permFile);
576 }
577
578 private void readPermissionsFromXml(File permFile) {
579 FileReader permReader = null;
580 try {
581 permReader = new FileReader(permFile);
582 } catch (FileNotFoundException e) {
583 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
584 return;
585 }
586
587 try {
588 XmlPullParser parser = Xml.newPullParser();
589 parser.setInput(permReader);
590
591 XmlUtils.beginDocument(parser, "permissions");
592
593 while (true) {
594 XmlUtils.nextElement(parser);
595 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
596 break;
597 }
598
599 String name = parser.getName();
600 if ("group".equals(name)) {
601 String gidStr = parser.getAttributeValue(null, "gid");
602 if (gidStr != null) {
603 int gid = Integer.parseInt(gidStr);
604 mGlobalGids = appendInt(mGlobalGids, gid);
605 } else {
606 Log.w(TAG, "<group> without gid at "
607 + parser.getPositionDescription());
608 }
609
610 XmlUtils.skipCurrentTag(parser);
611 continue;
612 } else if ("permission".equals(name)) {
613 String perm = parser.getAttributeValue(null, "name");
614 if (perm == null) {
615 Log.w(TAG, "<permission> without name at "
616 + parser.getPositionDescription());
617 XmlUtils.skipCurrentTag(parser);
618 continue;
619 }
620 perm = perm.intern();
621 readPermission(parser, perm);
622
623 } else if ("assign-permission".equals(name)) {
624 String perm = parser.getAttributeValue(null, "name");
625 if (perm == null) {
626 Log.w(TAG, "<assign-permission> without name at "
627 + parser.getPositionDescription());
628 XmlUtils.skipCurrentTag(parser);
629 continue;
630 }
631 String uidStr = parser.getAttributeValue(null, "uid");
632 if (uidStr == null) {
633 Log.w(TAG, "<assign-permission> without uid at "
634 + parser.getPositionDescription());
635 XmlUtils.skipCurrentTag(parser);
636 continue;
637 }
638 int uid = Process.getUidForName(uidStr);
639 if (uid < 0) {
640 Log.w(TAG, "<assign-permission> with unknown uid \""
641 + uidStr + "\" at "
642 + parser.getPositionDescription());
643 XmlUtils.skipCurrentTag(parser);
644 continue;
645 }
646 perm = perm.intern();
647 HashSet<String> perms = mSystemPermissions.get(uid);
648 if (perms == null) {
649 perms = new HashSet<String>();
650 mSystemPermissions.put(uid, perms);
651 }
652 perms.add(perm);
653 XmlUtils.skipCurrentTag(parser);
654
655 } else if ("library".equals(name)) {
656 String lname = parser.getAttributeValue(null, "name");
657 String lfile = parser.getAttributeValue(null, "file");
658 if (lname == null) {
659 Log.w(TAG, "<library> without name at "
660 + parser.getPositionDescription());
661 } else if (lfile == null) {
662 Log.w(TAG, "<library> without file at "
663 + parser.getPositionDescription());
664 } else {
665 Log.i(TAG, "Got library " + lname + " in " + lfile);
666 this.mSharedLibraries.put(lname, lfile);
667 }
668 XmlUtils.skipCurrentTag(parser);
669 continue;
670
671 } else {
672 XmlUtils.skipCurrentTag(parser);
673 continue;
674 }
675
676 }
677 } catch (XmlPullParserException e) {
678 Log.w(TAG, "Got execption parsing permissions.", e);
679 } catch (IOException e) {
680 Log.w(TAG, "Got execption parsing permissions.", e);
681 }
682 }
683
684 void readPermission(XmlPullParser parser, String name)
685 throws IOException, XmlPullParserException {
686
687 name = name.intern();
688
689 BasePermission bp = mSettings.mPermissions.get(name);
690 if (bp == null) {
691 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
692 mSettings.mPermissions.put(name, bp);
693 }
694 int outerDepth = parser.getDepth();
695 int type;
696 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
697 && (type != XmlPullParser.END_TAG
698 || parser.getDepth() > outerDepth)) {
699 if (type == XmlPullParser.END_TAG
700 || type == XmlPullParser.TEXT) {
701 continue;
702 }
703
704 String tagName = parser.getName();
705 if ("group".equals(tagName)) {
706 String gidStr = parser.getAttributeValue(null, "gid");
707 if (gidStr != null) {
708 int gid = Process.getGidForName(gidStr);
709 bp.gids = appendInt(bp.gids, gid);
710 } else {
711 Log.w(TAG, "<group> without gid at "
712 + parser.getPositionDescription());
713 }
714 }
715 XmlUtils.skipCurrentTag(parser);
716 }
717 }
718
719 static int[] appendInt(int[] cur, int val) {
720 if (cur == null) {
721 return new int[] { val };
722 }
723 final int N = cur.length;
724 for (int i=0; i<N; i++) {
725 if (cur[i] == val) {
726 return cur;
727 }
728 }
729 int[] ret = new int[N+1];
730 System.arraycopy(cur, 0, ret, 0, N);
731 ret[N] = val;
732 return ret;
733 }
734
735 static int[] appendInts(int[] cur, int[] add) {
736 if (add == null) return cur;
737 if (cur == null) return add;
738 final int N = add.length;
739 for (int i=0; i<N; i++) {
740 cur = appendInt(cur, add[i]);
741 }
742 return cur;
743 }
744
745 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
746 final PackageSetting ps = (PackageSetting)p.mExtras;
747 if (ps == null) {
748 return null;
749 }
750 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
751 return PackageParser.generatePackageInfo(p, gp.gids, flags);
752 }
753
754 public PackageInfo getPackageInfo(String packageName, int flags) {
755 synchronized (mPackages) {
756 PackageParser.Package p = mPackages.get(packageName);
757 if (Config.LOGV) Log.v(
758 TAG, "getApplicationInfo " + packageName
759 + ": " + p);
760 if (p != null) {
761 return generatePackageInfo(p, flags);
762 }
763 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
764 return generatePackageInfoFromSettingsLP(packageName, flags);
765 }
766 }
767 return null;
768 }
769
770 public int getPackageUid(String packageName) {
771 synchronized (mPackages) {
772 PackageParser.Package p = mPackages.get(packageName);
773 if(p != null) {
774 return p.applicationInfo.uid;
775 }
776 PackageSetting ps = mSettings.mPackages.get(packageName);
777 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
778 return -1;
779 }
780 p = ps.pkg;
781 return p != null ? p.applicationInfo.uid : -1;
782 }
783 }
784
785 public int[] getPackageGids(String packageName) {
786 synchronized (mPackages) {
787 PackageParser.Package p = mPackages.get(packageName);
788 if (Config.LOGV) Log.v(
789 TAG, "getApplicationInfo " + packageName
790 + ": " + p);
791 if (p != null) {
792 final PackageSetting ps = (PackageSetting)p.mExtras;
793 final SharedUserSetting suid = ps.sharedUser;
794 return suid != null ? suid.gids : ps.gids;
795 }
796 }
797 // stupid thing to indicate an error.
798 return new int[0];
799 }
800
801 public PermissionInfo getPermissionInfo(String name, int flags) {
802 synchronized (mPackages) {
803 final BasePermission p = mSettings.mPermissions.get(name);
804 if (p != null && p.perm != null) {
805 return PackageParser.generatePermissionInfo(p.perm, flags);
806 }
807 return null;
808 }
809 }
810
811 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
812 synchronized (mPackages) {
813 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
814 for (BasePermission p : mSettings.mPermissions.values()) {
815 if (group == null) {
816 if (p.perm.info.group == null) {
817 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
818 }
819 } else {
820 if (group.equals(p.perm.info.group)) {
821 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
822 }
823 }
824 }
825
826 if (out.size() > 0) {
827 return out;
828 }
829 return mPermissionGroups.containsKey(group) ? out : null;
830 }
831 }
832
833 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
834 synchronized (mPackages) {
835 return PackageParser.generatePermissionGroupInfo(
836 mPermissionGroups.get(name), flags);
837 }
838 }
839
840 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
841 synchronized (mPackages) {
842 final int N = mPermissionGroups.size();
843 ArrayList<PermissionGroupInfo> out
844 = new ArrayList<PermissionGroupInfo>(N);
845 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
846 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
847 }
848 return out;
849 }
850 }
851
852 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
853 PackageSetting ps = mSettings.mPackages.get(packageName);
854 if(ps != null) {
855 if(ps.pkg == null) {
856 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
857 if(pInfo != null) {
858 return pInfo.applicationInfo;
859 }
860 return null;
861 }
862 return PackageParser.generateApplicationInfo(ps.pkg, flags);
863 }
864 return null;
865 }
866
867 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
868 PackageSetting ps = mSettings.mPackages.get(packageName);
869 if(ps != null) {
870 if(ps.pkg == null) {
871 ps.pkg = new PackageParser.Package(packageName);
872 ps.pkg.applicationInfo.packageName = packageName;
873 }
874 return generatePackageInfo(ps.pkg, flags);
875 }
876 return null;
877 }
878
879 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
880 synchronized (mPackages) {
881 PackageParser.Package p = mPackages.get(packageName);
882 if (Config.LOGV) Log.v(
883 TAG, "getApplicationInfo " + packageName
884 + ": " + p);
885 if (p != null) {
886 // Note: isEnabledLP() does not apply here - always return info
887 return PackageParser.generateApplicationInfo(p, flags);
888 }
889 if ("android".equals(packageName)||"system".equals(packageName)) {
890 return mAndroidApplication;
891 }
892 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
893 return generateApplicationInfoFromSettingsLP(packageName, flags);
894 }
895 }
896 return null;
897 }
898
899
900 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
901 mContext.enforceCallingOrSelfPermission(
902 android.Manifest.permission.CLEAR_APP_CACHE, null);
903 // Queue up an async operation since clearing cache may take a little while.
904 mHandler.post(new Runnable() {
905 public void run() {
906 mHandler.removeCallbacks(this);
907 int retCode = -1;
908 if (mInstaller != null) {
909 retCode = mInstaller.freeCache(freeStorageSize);
910 if (retCode < 0) {
911 Log.w(TAG, "Couldn't clear application caches");
912 }
913 } //end if mInstaller
914 if (observer != null) {
915 try {
916 observer.onRemoveCompleted(null, (retCode >= 0));
917 } catch (RemoteException e) {
918 Log.w(TAG, "RemoveException when invoking call back");
919 }
920 }
921 }
922 });
923 }
924
925 public void freeStorage(final long freeStorageSize, final PendingIntent opFinishedIntent) {
926 mContext.enforceCallingOrSelfPermission(
927 android.Manifest.permission.CLEAR_APP_CACHE, null);
928 // Queue up an async operation since clearing cache may take a little while.
929 mHandler.post(new Runnable() {
930 public void run() {
931 mHandler.removeCallbacks(this);
932 int retCode = -1;
933 if (mInstaller != null) {
934 retCode = mInstaller.freeCache(freeStorageSize);
935 if (retCode < 0) {
936 Log.w(TAG, "Couldn't clear application caches");
937 }
938 }
939 if(opFinishedIntent != null) {
940 try {
941 // Callback via pending intent
942 opFinishedIntent.send((retCode >= 0) ? 1 : 0);
943 } catch (CanceledException e1) {
944 Log.i(TAG, "Failed to send pending intent");
945 }
946 }
947 }
948 });
949 }
950
951 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
952 synchronized (mPackages) {
953 PackageParser.Activity a = mActivities.mActivities.get(component);
954 if (Config.LOGV) Log.v(
955 TAG, "getActivityInfo " + component + ": " + a);
956 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
957 return PackageParser.generateActivityInfo(a, flags);
958 }
959 if (mResolveComponentName.equals(component)) {
960 return mResolveActivity;
961 }
962 }
963 return null;
964 }
965
966 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
967 synchronized (mPackages) {
968 PackageParser.Activity a = mReceivers.mActivities.get(component);
969 if (Config.LOGV) Log.v(
970 TAG, "getReceiverInfo " + component + ": " + a);
971 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
972 return PackageParser.generateActivityInfo(a, flags);
973 }
974 }
975 return null;
976 }
977
978 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
979 synchronized (mPackages) {
980 PackageParser.Service s = mServices.mServices.get(component);
981 if (Config.LOGV) Log.v(
982 TAG, "getServiceInfo " + component + ": " + s);
983 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
984 return PackageParser.generateServiceInfo(s, flags);
985 }
986 }
987 return null;
988 }
989
990 public String[] getSystemSharedLibraryNames() {
991 Set<String> libSet;
992 synchronized (mPackages) {
993 libSet = mSharedLibraries.keySet();
994 }
995 int size = libSet.size();
996 if (size > 0) {
997 String[] libs = new String[size];
998 libSet.toArray(libs);
999 return libs;
1000 }
1001 return null;
1002 }
1003
1004 public int checkPermission(String permName, String pkgName) {
1005 synchronized (mPackages) {
1006 PackageParser.Package p = mPackages.get(pkgName);
1007 if (p != null && p.mExtras != null) {
1008 PackageSetting ps = (PackageSetting)p.mExtras;
1009 if (ps.sharedUser != null) {
1010 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1011 return PackageManager.PERMISSION_GRANTED;
1012 }
1013 } else if (ps.grantedPermissions.contains(permName)) {
1014 return PackageManager.PERMISSION_GRANTED;
1015 }
1016 }
1017 }
1018 return PackageManager.PERMISSION_DENIED;
1019 }
1020
1021 public int checkUidPermission(String permName, int uid) {
1022 synchronized (mPackages) {
1023 Object obj = mSettings.getUserIdLP(uid);
1024 if (obj != null) {
1025 if (obj instanceof SharedUserSetting) {
1026 SharedUserSetting sus = (SharedUserSetting)obj;
1027 if (sus.grantedPermissions.contains(permName)) {
1028 return PackageManager.PERMISSION_GRANTED;
1029 }
1030 } else if (obj instanceof PackageSetting) {
1031 PackageSetting ps = (PackageSetting)obj;
1032 if (ps.grantedPermissions.contains(permName)) {
1033 return PackageManager.PERMISSION_GRANTED;
1034 }
1035 }
1036 } else {
1037 HashSet<String> perms = mSystemPermissions.get(uid);
1038 if (perms != null && perms.contains(permName)) {
1039 return PackageManager.PERMISSION_GRANTED;
1040 }
1041 }
1042 }
1043 return PackageManager.PERMISSION_DENIED;
1044 }
1045
1046 private BasePermission findPermissionTreeLP(String permName) {
1047 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1048 if (permName.startsWith(bp.name) &&
1049 permName.length() > bp.name.length() &&
1050 permName.charAt(bp.name.length()) == '.') {
1051 return bp;
1052 }
1053 }
1054 return null;
1055 }
1056
1057 private BasePermission checkPermissionTreeLP(String permName) {
1058 if (permName != null) {
1059 BasePermission bp = findPermissionTreeLP(permName);
1060 if (bp != null) {
1061 if (bp.uid == Binder.getCallingUid()) {
1062 return bp;
1063 }
1064 throw new SecurityException("Calling uid "
1065 + Binder.getCallingUid()
1066 + " is not allowed to add to permission tree "
1067 + bp.name + " owned by uid " + bp.uid);
1068 }
1069 }
1070 throw new SecurityException("No permission tree found for " + permName);
1071 }
1072
1073 public boolean addPermission(PermissionInfo info) {
1074 synchronized (mPackages) {
1075 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1076 throw new SecurityException("Label must be specified in permission");
1077 }
1078 BasePermission tree = checkPermissionTreeLP(info.name);
1079 BasePermission bp = mSettings.mPermissions.get(info.name);
1080 boolean added = bp == null;
1081 if (added) {
1082 bp = new BasePermission(info.name, tree.sourcePackage,
1083 BasePermission.TYPE_DYNAMIC);
1084 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1085 throw new SecurityException(
1086 "Not allowed to modify non-dynamic permission "
1087 + info.name);
1088 }
1089 bp.perm = new PackageParser.Permission(tree.perm.owner,
1090 new PermissionInfo(info));
1091 bp.perm.info.packageName = tree.perm.info.packageName;
1092 bp.uid = tree.uid;
1093 if (added) {
1094 mSettings.mPermissions.put(info.name, bp);
1095 }
1096 mSettings.writeLP();
1097 return added;
1098 }
1099 }
1100
1101 public void removePermission(String name) {
1102 synchronized (mPackages) {
1103 checkPermissionTreeLP(name);
1104 BasePermission bp = mSettings.mPermissions.get(name);
1105 if (bp != null) {
1106 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1107 throw new SecurityException(
1108 "Not allowed to modify non-dynamic permission "
1109 + name);
1110 }
1111 mSettings.mPermissions.remove(name);
1112 mSettings.writeLP();
1113 }
1114 }
1115 }
1116
1117 public int checkSignatures(String pkg1, String pkg2) {
1118 synchronized (mPackages) {
1119 PackageParser.Package p1 = mPackages.get(pkg1);
1120 PackageParser.Package p2 = mPackages.get(pkg2);
1121 if (p1 == null || p1.mExtras == null
1122 || p2 == null || p2.mExtras == null) {
1123 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1124 }
1125 return checkSignaturesLP(p1, p2);
1126 }
1127 }
1128
1129 int checkSignaturesLP(PackageParser.Package p1, PackageParser.Package p2) {
1130 if (p1.mSignatures == null) {
1131 return p2.mSignatures == null
1132 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1133 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1134 }
1135 if (p2.mSignatures == null) {
1136 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1137 }
1138 final int N1 = p1.mSignatures.length;
1139 final int N2 = p2.mSignatures.length;
1140 for (int i=0; i<N1; i++) {
1141 boolean match = false;
1142 for (int j=0; j<N2; j++) {
1143 if (p1.mSignatures[i].equals(p2.mSignatures[j])) {
1144 match = true;
1145 break;
1146 }
1147 }
1148 if (!match) {
1149 return PackageManager.SIGNATURE_NO_MATCH;
1150 }
1151 }
1152 return PackageManager.SIGNATURE_MATCH;
1153 }
1154
1155 public String[] getPackagesForUid(int uid) {
1156 synchronized (mPackages) {
1157 Object obj = mSettings.getUserIdLP(uid);
1158 if (obj instanceof SharedUserSetting) {
1159 SharedUserSetting sus = (SharedUserSetting)obj;
1160 final int N = sus.packages.size();
1161 String[] res = new String[N];
1162 Iterator<PackageSetting> it = sus.packages.iterator();
1163 int i=0;
1164 while (it.hasNext()) {
1165 res[i++] = it.next().name;
1166 }
1167 return res;
1168 } else if (obj instanceof PackageSetting) {
1169 PackageSetting ps = (PackageSetting)obj;
1170 return new String[] { ps.name };
1171 }
1172 }
1173 return null;
1174 }
1175
1176 public String getNameForUid(int uid) {
1177 synchronized (mPackages) {
1178 Object obj = mSettings.getUserIdLP(uid);
1179 if (obj instanceof SharedUserSetting) {
1180 SharedUserSetting sus = (SharedUserSetting)obj;
1181 return sus.name + ":" + sus.userId;
1182 } else if (obj instanceof PackageSetting) {
1183 PackageSetting ps = (PackageSetting)obj;
1184 return ps.name;
1185 }
1186 }
1187 return null;
1188 }
1189
1190 public int getUidForSharedUser(String sharedUserName) {
1191 if(sharedUserName == null) {
1192 return -1;
1193 }
1194 synchronized (mPackages) {
1195 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1196 if(suid == null) {
1197 return -1;
1198 }
1199 return suid.userId;
1200 }
1201 }
1202
1203 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1204 int flags) {
1205 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
1206 if (query != null) {
1207 final int N = query.size();
1208 if (N == 1) {
1209 return query.get(0);
1210 } else if (N > 1) {
1211 // If there is more than one activity with the same priority,
1212 // then let the user decide between them.
1213 ResolveInfo r0 = query.get(0);
1214 ResolveInfo r1 = query.get(1);
1215 if (false) {
1216 System.out.println(r0.activityInfo.name +
1217 "=" + r0.priority + " vs " +
1218 r1.activityInfo.name +
1219 "=" + r1.priority);
1220 }
1221 // If the first activity has a higher priority, or a different
1222 // default, then it is always desireable to pick it.
1223 if (r0.priority != r1.priority
1224 || r0.preferredOrder != r1.preferredOrder
1225 || r0.isDefault != r1.isDefault) {
1226 return query.get(0);
1227 }
1228 // If we have saved a preference for a preferred activity for
1229 // this Intent, use that.
1230 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1231 flags, query, r0.priority);
1232 if (ri != null) {
1233 return ri;
1234 }
1235 return mResolveInfo;
1236 }
1237 }
1238 return null;
1239 }
1240
1241 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1242 int flags, List<ResolveInfo> query, int priority) {
1243 synchronized (mPackages) {
1244 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1245 List<PreferredActivity> prefs =
1246 mSettings.mPreferredActivities.queryIntent(null,
1247 intent, resolvedType,
1248 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1249 if (prefs != null && prefs.size() > 0) {
1250 // First figure out how good the original match set is.
1251 // We will only allow preferred activities that came
1252 // from the same match quality.
1253 int match = 0;
1254 final int N = query.size();
1255 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1256 for (int j=0; j<N; j++) {
1257 ResolveInfo ri = query.get(j);
1258 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1259 + ": 0x" + Integer.toHexString(match));
1260 if (ri.match > match) match = ri.match;
1261 }
1262 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1263 + Integer.toHexString(match));
1264 match &= IntentFilter.MATCH_CATEGORY_MASK;
1265 final int M = prefs.size();
1266 for (int i=0; i<M; i++) {
1267 PreferredActivity pa = prefs.get(i);
1268 if (pa.mMatch != match) {
1269 continue;
1270 }
1271 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1272 if (DEBUG_PREFERRED) {
1273 Log.v(TAG, "Got preferred activity:");
1274 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1275 }
1276 if (ai != null) {
1277 for (int j=0; j<N; j++) {
1278 ResolveInfo ri = query.get(j);
1279 if (!ri.activityInfo.applicationInfo.packageName
1280 .equals(ai.applicationInfo.packageName)) {
1281 continue;
1282 }
1283 if (!ri.activityInfo.name.equals(ai.name)) {
1284 continue;
1285 }
1286
1287 // Okay we found a previously set preferred app.
1288 // If the result set is different from when this
1289 // was created, we need to clear it and re-ask the
1290 // user their preference.
1291 if (!pa.sameSet(query, priority)) {
1292 Log.i(TAG, "Result set changed, dropping preferred activity for "
1293 + intent + " type " + resolvedType);
1294 mSettings.mPreferredActivities.removeFilter(pa);
1295 return null;
1296 }
1297
1298 // Yay!
1299 return ri;
1300 }
1301 }
1302 }
1303 }
1304 }
1305 return null;
1306 }
1307
1308 public List<ResolveInfo> queryIntentActivities(Intent intent,
1309 String resolvedType, int flags) {
1310 ComponentName comp = intent.getComponent();
1311 if (comp != null) {
1312 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1313 ActivityInfo ai = getActivityInfo(comp, flags);
1314 if (ai != null) {
1315 ResolveInfo ri = new ResolveInfo();
1316 ri.activityInfo = ai;
1317 list.add(ri);
1318 }
1319 return list;
1320 }
1321
1322 synchronized (mPackages) {
1323 return (List<ResolveInfo>)mActivities.
1324 queryIntent(null, intent, resolvedType, flags);
1325 }
1326 }
1327
1328 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1329 Intent[] specifics, String[] specificTypes, Intent intent,
1330 String resolvedType, int flags) {
1331 final String resultsAction = intent.getAction();
1332
1333 List<ResolveInfo> results = queryIntentActivities(
1334 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1335 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1336
1337 int specificsPos = 0;
1338 int N;
1339
1340 // todo: note that the algorithm used here is O(N^2). This
1341 // isn't a problem in our current environment, but if we start running
1342 // into situations where we have more than 5 or 10 matches then this
1343 // should probably be changed to something smarter...
1344
1345 // First we go through and resolve each of the specific items
1346 // that were supplied, taking care of removing any corresponding
1347 // duplicate items in the generic resolve list.
1348 if (specifics != null) {
1349 for (int i=0; i<specifics.length; i++) {
1350 final Intent sintent = specifics[i];
1351 if (sintent == null) {
1352 continue;
1353 }
1354
1355 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1356 String action = sintent.getAction();
1357 if (resultsAction != null && resultsAction.equals(action)) {
1358 // If this action was explicitly requested, then don't
1359 // remove things that have it.
1360 action = null;
1361 }
1362 ComponentName comp = sintent.getComponent();
1363 ResolveInfo ri = null;
1364 ActivityInfo ai = null;
1365 if (comp == null) {
1366 ri = resolveIntent(
1367 sintent,
1368 specificTypes != null ? specificTypes[i] : null,
1369 flags);
1370 if (ri == null) {
1371 continue;
1372 }
1373 if (ri == mResolveInfo) {
1374 // ACK! Must do something better with this.
1375 }
1376 ai = ri.activityInfo;
1377 comp = new ComponentName(ai.applicationInfo.packageName,
1378 ai.name);
1379 } else {
1380 ai = getActivityInfo(comp, flags);
1381 if (ai == null) {
1382 continue;
1383 }
1384 }
1385
1386 // Look for any generic query activities that are duplicates
1387 // of this specific one, and remove them from the results.
1388 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1389 N = results.size();
1390 int j;
1391 for (j=specificsPos; j<N; j++) {
1392 ResolveInfo sri = results.get(j);
1393 if ((sri.activityInfo.name.equals(comp.getClassName())
1394 && sri.activityInfo.applicationInfo.packageName.equals(
1395 comp.getPackageName()))
1396 || (action != null && sri.filter.matchAction(action))) {
1397 results.remove(j);
1398 if (Config.LOGV) Log.v(
1399 TAG, "Removing duplicate item from " + j
1400 + " due to specific " + specificsPos);
1401 if (ri == null) {
1402 ri = sri;
1403 }
1404 j--;
1405 N--;
1406 }
1407 }
1408
1409 // Add this specific item to its proper place.
1410 if (ri == null) {
1411 ri = new ResolveInfo();
1412 ri.activityInfo = ai;
1413 }
1414 results.add(specificsPos, ri);
1415 ri.specificIndex = i;
1416 specificsPos++;
1417 }
1418 }
1419
1420 // Now we go through the remaining generic results and remove any
1421 // duplicate actions that are found here.
1422 N = results.size();
1423 for (int i=specificsPos; i<N-1; i++) {
1424 final ResolveInfo rii = results.get(i);
1425 if (rii.filter == null) {
1426 continue;
1427 }
1428
1429 // Iterate over all of the actions of this result's intent
1430 // filter... typically this should be just one.
1431 final Iterator<String> it = rii.filter.actionsIterator();
1432 if (it == null) {
1433 continue;
1434 }
1435 while (it.hasNext()) {
1436 final String action = it.next();
1437 if (resultsAction != null && resultsAction.equals(action)) {
1438 // If this action was explicitly requested, then don't
1439 // remove things that have it.
1440 continue;
1441 }
1442 for (int j=i+1; j<N; j++) {
1443 final ResolveInfo rij = results.get(j);
1444 if (rij.filter != null && rij.filter.hasAction(action)) {
1445 results.remove(j);
1446 if (Config.LOGV) Log.v(
1447 TAG, "Removing duplicate item from " + j
1448 + " due to action " + action + " at " + i);
1449 j--;
1450 N--;
1451 }
1452 }
1453 }
1454
1455 // If the caller didn't request filter information, drop it now
1456 // so we don't have to marshall/unmarshall it.
1457 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1458 rii.filter = null;
1459 }
1460 }
1461
1462 // Filter out the caller activity if so requested.
1463 if (caller != null) {
1464 N = results.size();
1465 for (int i=0; i<N; i++) {
1466 ActivityInfo ainfo = results.get(i).activityInfo;
1467 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1468 && caller.getClassName().equals(ainfo.name)) {
1469 results.remove(i);
1470 break;
1471 }
1472 }
1473 }
1474
1475 // If the caller didn't request filter information,
1476 // drop them now so we don't have to
1477 // marshall/unmarshall it.
1478 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1479 N = results.size();
1480 for (int i=0; i<N; i++) {
1481 results.get(i).filter = null;
1482 }
1483 }
1484
1485 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1486 return results;
1487 }
1488
1489 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1490 String resolvedType, int flags) {
1491 synchronized (mPackages) {
1492 return (List<ResolveInfo>)mReceivers.
1493 queryIntent(null, intent, resolvedType, flags);
1494 }
1495 }
1496
1497 public ResolveInfo resolveService(Intent intent, String resolvedType,
1498 int flags) {
1499 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1500 flags);
1501 if (query != null) {
1502 if (query.size() >= 1) {
1503 // If there is more than one service with the same priority,
1504 // just arbitrarily pick the first one.
1505 return query.get(0);
1506 }
1507 }
1508 return null;
1509 }
1510
1511 public List<ResolveInfo> queryIntentServices(Intent intent,
1512 String resolvedType, int flags) {
1513 ComponentName comp = intent.getComponent();
1514 if (comp != null) {
1515 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1516 ServiceInfo si = getServiceInfo(comp, flags);
1517 if (si != null) {
1518 ResolveInfo ri = new ResolveInfo();
1519 ri.serviceInfo = si;
1520 list.add(ri);
1521 }
1522 return list;
1523 }
1524
1525 synchronized (mPackages) {
1526 return (List<ResolveInfo>)mServices.
1527 queryIntent(null, intent, resolvedType, flags);
1528 }
1529 }
1530
1531 public List<PackageInfo> getInstalledPackages(int flags) {
1532 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1533
1534 synchronized (mPackages) {
1535 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1536 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1537 while (i.hasNext()) {
1538 final PackageSetting ps = i.next();
1539 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1540 if(psPkg != null) {
1541 finalList.add(psPkg);
1542 }
1543 }
1544 }
1545 else {
1546 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1547 while (i.hasNext()) {
1548 final PackageParser.Package p = i.next();
1549 if (p.applicationInfo != null) {
1550 PackageInfo pi = generatePackageInfo(p, flags);
1551 if(pi != null) {
1552 finalList.add(pi);
1553 }
1554 }
1555 }
1556 }
1557 }
1558 return finalList;
1559 }
1560
1561 public List<ApplicationInfo> getInstalledApplications(int flags) {
1562 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1563 synchronized(mPackages) {
1564 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1565 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1566 while (i.hasNext()) {
1567 final PackageSetting ps = i.next();
1568 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1569 if(ai != null) {
1570 finalList.add(ai);
1571 }
1572 }
1573 }
1574 else {
1575 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1576 while (i.hasNext()) {
1577 final PackageParser.Package p = i.next();
1578 if (p.applicationInfo != null) {
1579 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1580 if(ai != null) {
1581 finalList.add(ai);
1582 }
1583 }
1584 }
1585 }
1586 }
1587 return finalList;
1588 }
1589
1590 public List<ApplicationInfo> getPersistentApplications(int flags) {
1591 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1592
1593 synchronized (mPackages) {
1594 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1595 while (i.hasNext()) {
1596 PackageParser.Package p = i.next();
1597 if (p.applicationInfo != null
1598 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1599 && (!mSafeMode || (p.applicationInfo.flags
1600 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1601 finalList.add(p.applicationInfo);
1602 }
1603 }
1604 }
1605
1606 return finalList;
1607 }
1608
1609 public ProviderInfo resolveContentProvider(String name, int flags) {
1610 synchronized (mPackages) {
1611 final PackageParser.Provider provider = mProviders.get(name);
1612 return provider != null
1613 && mSettings.isEnabledLP(provider.info, flags)
1614 && (!mSafeMode || (provider.info.applicationInfo.flags
1615 &ApplicationInfo.FLAG_SYSTEM) != 0)
1616 ? PackageParser.generateProviderInfo(provider, flags)
1617 : null;
1618 }
1619 }
1620
Fred Quintana718d8a22009-04-29 17:53:20 -07001621 /**
1622 * @deprecated
1623 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 public void querySyncProviders(List outNames, List outInfo) {
1625 synchronized (mPackages) {
1626 Iterator<Map.Entry<String, PackageParser.Provider>> i
1627 = mProviders.entrySet().iterator();
1628
1629 while (i.hasNext()) {
1630 Map.Entry<String, PackageParser.Provider> entry = i.next();
1631 PackageParser.Provider p = entry.getValue();
1632
1633 if (p.syncable
1634 && (!mSafeMode || (p.info.applicationInfo.flags
1635 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1636 outNames.add(entry.getKey());
1637 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1638 }
1639 }
1640 }
1641 }
1642
1643 public List<ProviderInfo> queryContentProviders(String processName,
1644 int uid, int flags) {
1645 ArrayList<ProviderInfo> finalList = null;
1646
1647 synchronized (mPackages) {
1648 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1649 while (i.hasNext()) {
1650 PackageParser.Provider p = i.next();
1651 if (p.info.authority != null
1652 && (processName == null ||
1653 (p.info.processName.equals(processName)
1654 && p.info.applicationInfo.uid == uid))
1655 && mSettings.isEnabledLP(p.info, flags)
1656 && (!mSafeMode || (p.info.applicationInfo.flags
1657 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1658 if (finalList == null) {
1659 finalList = new ArrayList<ProviderInfo>(3);
1660 }
1661 finalList.add(PackageParser.generateProviderInfo(p,
1662 flags));
1663 }
1664 }
1665 }
1666
1667 if (finalList != null) {
1668 Collections.sort(finalList, mProviderInitOrderSorter);
1669 }
1670
1671 return finalList;
1672 }
1673
1674 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1675 int flags) {
1676 synchronized (mPackages) {
1677 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1678 return PackageParser.generateInstrumentationInfo(i, flags);
1679 }
1680 }
1681
1682 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1683 int flags) {
1684 ArrayList<InstrumentationInfo> finalList =
1685 new ArrayList<InstrumentationInfo>();
1686
1687 synchronized (mPackages) {
1688 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1689 while (i.hasNext()) {
1690 PackageParser.Instrumentation p = i.next();
1691 if (targetPackage == null
1692 || targetPackage.equals(p.info.targetPackage)) {
1693 finalList.add(PackageParser.generateInstrumentationInfo(p,
1694 flags));
1695 }
1696 }
1697 }
1698
1699 return finalList;
1700 }
1701
1702 private void scanDirLI(File dir, int flags, int scanMode) {
1703 Log.d(TAG, "Scanning app dir " + dir);
1704
1705 String[] files = dir.list();
1706
1707 int i;
1708 for (i=0; i<files.length; i++) {
1709 File file = new File(dir, files[i]);
1710 PackageParser.Package pkg = scanPackageLI(file, file, file,
1711 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1712 }
1713 }
1714
1715 private static void reportSettingsProblem(int priority, String msg) {
1716 try {
1717 File dataDir = Environment.getDataDirectory();
1718 File systemDir = new File(dataDir, "system");
1719 File fname = new File(systemDir, "uiderrors.txt");
1720 FileOutputStream out = new FileOutputStream(fname, true);
1721 PrintWriter pw = new PrintWriter(out);
1722 pw.println(msg);
1723 pw.close();
1724 FileUtils.setPermissions(
1725 fname.toString(),
1726 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1727 -1, -1);
1728 } catch (java.io.IOException e) {
1729 }
1730 Log.println(priority, TAG, msg);
1731 }
1732
1733 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1734 PackageParser.Package pkg, File srcFile, int parseFlags) {
1735 if (GET_CERTIFICATES) {
1736 if (ps == null || !ps.codePath.equals(srcFile)
1737 || ps.getTimeStamp() != srcFile.lastModified()) {
1738 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1739 if (!pp.collectCertificates(pkg, parseFlags)) {
1740 mLastScanError = pp.getParseError();
1741 return false;
1742 }
1743 }
1744 }
1745 return true;
1746 }
1747
1748 /*
1749 * Scan a package and return the newly parsed package.
1750 * Returns null in case of errors and the error code is stored in mLastScanError
1751 */
1752 private PackageParser.Package scanPackageLI(File scanFile,
1753 File destCodeFile, File destResourceFile, int parseFlags,
1754 int scanMode) {
1755 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1756 parseFlags |= mDefParseFlags;
1757 PackageParser pp = new PackageParser(scanFile.getPath());
1758 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07001759 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 final PackageParser.Package pkg = pp.parsePackage(scanFile,
1761 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
1762 if (pkg == null) {
1763 mLastScanError = pp.getParseError();
1764 return null;
1765 }
1766 PackageSetting ps;
1767 PackageSetting updatedPkg;
1768 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001769 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
1771 }
1772 if (updatedPkg != null) {
1773 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
1774 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
1775 }
1776 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1777 // Check for updated system applications here
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001778 if (updatedPkg != null) {
1779 if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
1780 if (pkg.mVersionCode <= ps.versionCode) {
1781 // The system package has been updated and the code path does not match
1782 // Ignore entry. Just return
1783 Log.w(TAG, "Package:" + pkg.packageName +
1784 " has been updated. Ignoring the one from path:"+scanFile);
1785 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1786 return null;
1787 } else {
1788 // Delete the older apk pointed to by ps
1789 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
1790 mSettings.enableSystemPackageLP(ps.name);
1791 }
1792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 }
1794 }
1795 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
1796 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
1797 return null;
1798 }
1799 // The apk is forward locked (not public) if its code and resources
1800 // are kept in different files.
1801 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
1802 scanMode |= SCAN_FORWARD_LOCKED;
1803 }
1804 // Note that we invoke the following method only if we are about to unpack an application
1805 return scanPackageLI(scanFile, destCodeFile, destResourceFile,
1806 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
1807 }
1808
1809 private static String fixProcessName(String defProcessName,
1810 String processName, int uid) {
1811 if (processName == null) {
1812 return defProcessName;
1813 }
1814 return processName;
1815 }
1816
1817 private boolean verifySignaturesLP(PackageSetting pkgSetting,
1818 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
1819 if (pkg.mSignatures != null) {
1820 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
1821 updateSignature)) {
1822 Log.e(TAG, "Package " + pkg.packageName
1823 + " signatures do not match the previously installed version; ignoring!");
1824 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1825 return false;
1826 }
1827
1828 if (pkgSetting.sharedUser != null) {
1829 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1830 pkg.mSignatures, updateSignature)) {
1831 Log.e(TAG, "Package " + pkg.packageName
1832 + " has no signatures that match those in shared user "
1833 + pkgSetting.sharedUser.name + "; ignoring!");
1834 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
1835 return false;
1836 }
1837 }
1838 } else {
1839 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1840 }
1841 return true;
1842 }
1843
1844 private PackageParser.Package scanPackageLI(
1845 File scanFile, File destCodeFile, File destResourceFile,
1846 PackageParser.Package pkg, int parseFlags, int scanMode) {
1847
1848 mScanningPath = scanFile;
1849 if (pkg == null) {
1850 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1851 return null;
1852 }
1853
1854 final String pkgName = pkg.applicationInfo.packageName;
1855 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1856 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
1857 }
1858
1859 if (pkgName.equals("android")) {
1860 synchronized (mPackages) {
1861 if (mAndroidApplication != null) {
1862 Log.w(TAG, "*************************************************");
1863 Log.w(TAG, "Core android package being redefined. Skipping.");
1864 Log.w(TAG, " file=" + mScanningPath);
1865 Log.w(TAG, "*************************************************");
1866 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1867 return null;
1868 }
1869
1870 // Set up information for our fall-back user intent resolution
1871 // activity.
1872 mPlatformPackage = pkg;
1873 pkg.mVersionCode = mSdkVersion;
1874 mAndroidApplication = pkg.applicationInfo;
1875 mResolveActivity.applicationInfo = mAndroidApplication;
1876 mResolveActivity.name = ResolverActivity.class.getName();
1877 mResolveActivity.packageName = mAndroidApplication.packageName;
1878 mResolveActivity.processName = mAndroidApplication.processName;
1879 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1880 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1881 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
1882 mResolveActivity.exported = true;
1883 mResolveActivity.enabled = true;
1884 mResolveInfo.activityInfo = mResolveActivity;
1885 mResolveInfo.priority = 0;
1886 mResolveInfo.preferredOrder = 0;
1887 mResolveInfo.match = 0;
1888 mResolveComponentName = new ComponentName(
1889 mAndroidApplication.packageName, mResolveActivity.name);
1890 }
1891 }
1892
1893 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
1894 TAG, "Scanning package " + pkgName);
1895 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
1896 Log.w(TAG, "*************************************************");
1897 Log.w(TAG, "Application package " + pkgName
1898 + " already installed. Skipping duplicate.");
1899 Log.w(TAG, "*************************************************");
1900 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1901 return null;
1902 }
1903
1904 SharedUserSetting suid = null;
1905 PackageSetting pkgSetting = null;
1906
1907 boolean removeExisting = false;
1908
1909 synchronized (mPackages) {
1910 // Check all shared libraries and map to their actual file path.
1911 if (pkg.usesLibraryFiles != null) {
1912 for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
1913 String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
1914 if (file == null) {
1915 Log.e(TAG, "Package " + pkg.packageName
1916 + " requires unavailable shared library "
1917 + pkg.usesLibraryFiles[i] + "; ignoring!");
1918 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
1919 return null;
1920 }
1921 pkg.usesLibraryFiles[i] = file;
1922 }
1923 }
1924
1925 if (pkg.mSharedUserId != null) {
1926 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
1927 pkg.applicationInfo.flags, true);
1928 if (suid == null) {
1929 Log.w(TAG, "Creating application package " + pkgName
1930 + " for shared user failed");
1931 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1932 return null;
1933 }
1934 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
1935 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
1936 + suid.userId + "): packages=" + suid.packages);
1937 }
1938 }
1939
1940 // Just create the setting, don't add it yet
1941 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
1942 destResourceFile, pkg.applicationInfo.flags, true, false);
1943 if (pkgSetting == null) {
1944 Log.w(TAG, "Creating application package " + pkgName + " failed");
1945 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1946 return null;
1947 }
1948 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
1949 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
1950 }
1951
1952 pkg.applicationInfo.uid = pkgSetting.userId;
1953 pkg.mExtras = pkgSetting;
1954
1955 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
1956 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
1957 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
1958 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1959 return null;
1960 }
1961 // The signature has changed, but this package is in the system
1962 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07001963 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 // However... if this package is part of a shared user, but it
1965 // doesn't match the signature of the shared user, let's fail.
1966 // What this means is that you can't change the signatures
1967 // associated with an overall shared user, which doesn't seem all
1968 // that unreasonable.
1969 if (pkgSetting.sharedUser != null) {
1970 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1971 pkg.mSignatures, false)) {
1972 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
1973 return null;
1974 }
1975 }
1976 removeExisting = true;
1977 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001978
1979 // Verify that this new package doesn't have any content providers
1980 // that conflict with existing packages. Only do this if the
1981 // package isn't already installed, since we don't want to break
1982 // things that are installed.
1983 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
1984 int N = pkg.providers.size();
1985 int i;
1986 for (i=0; i<N; i++) {
1987 PackageParser.Provider p = pkg.providers.get(i);
1988 String names[] = p.info.authority.split(";");
1989 for (int j = 0; j < names.length; j++) {
1990 if (mProviders.containsKey(names[j])) {
1991 PackageParser.Provider other = mProviders.get(names[j]);
1992 Log.w(TAG, "Can't install because provider name " + names[j] +
1993 " (in package " + pkg.applicationInfo.packageName +
1994 ") is already used by "
1995 + ((other != null && other.component != null)
1996 ? other.component.getPackageName() : "?"));
1997 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
1998 return null;
1999 }
2000 }
2001 }
2002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 }
2004
2005 if (removeExisting) {
2006 if (mInstaller != null) {
2007 int ret = mInstaller.remove(pkgName);
2008 if (ret != 0) {
2009 String msg = "System package " + pkg.packageName
2010 + " could not have data directory erased after signature change.";
2011 reportSettingsProblem(Log.WARN, msg);
2012 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2013 return null;
2014 }
2015 }
2016 Log.w(TAG, "System package " + pkg.packageName
2017 + " signature changed: existing data removed.");
2018 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2019 }
2020
2021 long scanFileTime = scanFile.lastModified();
2022 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2023 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2024 pkg.applicationInfo.processName = fixProcessName(
2025 pkg.applicationInfo.packageName,
2026 pkg.applicationInfo.processName,
2027 pkg.applicationInfo.uid);
2028 pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
2029
2030 File dataPath;
2031 if (mPlatformPackage == pkg) {
2032 // The system package is special.
2033 dataPath = new File (Environment.getDataDirectory(), "system");
2034 pkg.applicationInfo.dataDir = dataPath.getPath();
2035 } else {
2036 // This is a normal package, need to make its data directory.
2037 dataPath = new File(mAppDataDir, pkgName);
2038 if (dataPath.exists()) {
2039 mOutPermissions[1] = 0;
2040 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2041 if (mOutPermissions[1] == pkg.applicationInfo.uid
2042 || !Process.supportsProcesses()) {
2043 pkg.applicationInfo.dataDir = dataPath.getPath();
2044 } else {
2045 boolean recovered = false;
2046 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2047 // If this is a system app, we can at least delete its
2048 // current data so the application will still work.
2049 if (mInstaller != null) {
2050 int ret = mInstaller.remove(pkgName);
2051 if(ret >= 0) {
2052 // Old data gone!
2053 String msg = "System package " + pkg.packageName
2054 + " has changed from uid: "
2055 + mOutPermissions[1] + " to "
2056 + pkg.applicationInfo.uid + "; old data erased";
2057 reportSettingsProblem(Log.WARN, msg);
2058 recovered = true;
2059
2060 // And now re-install the app.
2061 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2062 pkg.applicationInfo.uid);
2063 if (ret == -1) {
2064 // Ack should not happen!
2065 msg = "System package " + pkg.packageName
2066 + " could not have data directory re-created after delete.";
2067 reportSettingsProblem(Log.WARN, msg);
2068 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2069 return null;
2070 }
2071 }
2072 }
2073 if (!recovered) {
2074 mHasSystemUidErrors = true;
2075 }
2076 }
2077 if (!recovered) {
2078 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2079 + pkg.applicationInfo.uid + "/fs_"
2080 + mOutPermissions[1];
2081 String msg = "Package " + pkg.packageName
2082 + " has mismatched uid: "
2083 + mOutPermissions[1] + " on disk, "
2084 + pkg.applicationInfo.uid + " in settings";
2085 synchronized (mPackages) {
2086 if (!mReportedUidError) {
2087 mReportedUidError = true;
2088 msg = msg + "; read messages:\n"
2089 + mSettings.getReadMessagesLP();
2090 }
2091 reportSettingsProblem(Log.ERROR, msg);
2092 }
2093 }
2094 }
2095 pkg.applicationInfo.dataDir = dataPath.getPath();
2096 } else {
2097 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2098 Log.v(TAG, "Want this data dir: " + dataPath);
2099 //invoke installer to do the actual installation
2100 if (mInstaller != null) {
2101 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2102 pkg.applicationInfo.uid);
2103 if(ret < 0) {
2104 // Error from installer
2105 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2106 return null;
2107 }
2108 } else {
2109 dataPath.mkdirs();
2110 if (dataPath.exists()) {
2111 FileUtils.setPermissions(
2112 dataPath.toString(),
2113 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2114 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2115 }
2116 }
2117 if (dataPath.exists()) {
2118 pkg.applicationInfo.dataDir = dataPath.getPath();
2119 } else {
2120 Log.w(TAG, "Unable to create data directory: " + dataPath);
2121 pkg.applicationInfo.dataDir = null;
2122 }
2123 }
2124 }
2125
2126 // Perform shared library installation and dex validation and
2127 // optimization, if this is not a system app.
2128 if (mInstaller != null) {
2129 String path = scanFile.getPath();
2130 if (scanFileNewer) {
2131 Log.i(TAG, path + " changed; unpacking");
2132 try {
2133 cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2134 } catch (IOException e) {
2135 Log.e(TAG, "Failure extracting shared libs", e);
2136 if(mInstaller != null) {
2137 mInstaller.remove(pkgName);
2138 } else {
2139 dataPath.delete();
2140 }
2141 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2142 return null;
2143 }
2144 }
2145
2146 if ((scanMode&SCAN_NO_DEX) == 0
2147 && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
2148 int ret = 0;
2149 try {
2150 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2151 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2152 (scanMode&SCAN_FORWARD_LOCKED) == 0);
2153 }
2154 } catch (FileNotFoundException e) {
2155 Log.w(TAG, "Apk not found for dexopt: " + path);
2156 ret = -1;
2157 } catch (IOException e) {
2158 Log.w(TAG, "Exception reading apk: " + path, e);
2159 ret = -1;
2160 }
2161 if (ret < 0) {
2162 //error from installer
2163 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2164 return null;
2165 }
2166 }
2167 }
2168
2169 if (mFactoryTest && pkg.requestedPermissions.contains(
2170 android.Manifest.permission.FACTORY_TEST)) {
2171 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2172 }
2173
2174 if ((scanMode&SCAN_MONITOR) != 0) {
2175 pkg.mPath = destCodeFile.getAbsolutePath();
2176 mAppDirs.put(pkg.mPath, pkg);
2177 }
2178
2179 synchronized (mPackages) {
2180 // We don't expect installation to fail beyond this point
2181 // Add the new setting to mSettings
2182 mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
2183 // Add the new setting to mPackages
2184 mPackages.put(pkg.applicationInfo.packageName, pkg);
2185 int N = pkg.providers.size();
2186 StringBuilder r = null;
2187 int i;
2188 for (i=0; i<N; i++) {
2189 PackageParser.Provider p = pkg.providers.get(i);
2190 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2191 p.info.processName, pkg.applicationInfo.uid);
2192 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2193 p.info.name), p);
2194 p.syncable = p.info.isSyncable;
2195 String names[] = p.info.authority.split(";");
2196 p.info.authority = null;
2197 for (int j = 0; j < names.length; j++) {
2198 if (j == 1 && p.syncable) {
2199 // We only want the first authority for a provider to possibly be
2200 // syncable, so if we already added this provider using a different
2201 // authority clear the syncable flag. We copy the provider before
2202 // changing it because the mProviders object contains a reference
2203 // to a provider that we don't want to change.
2204 // Only do this for the second authority since the resulting provider
2205 // object can be the same for all future authorities for this provider.
2206 p = new PackageParser.Provider(p);
2207 p.syncable = false;
2208 }
2209 if (!mProviders.containsKey(names[j])) {
2210 mProviders.put(names[j], p);
2211 if (p.info.authority == null) {
2212 p.info.authority = names[j];
2213 } else {
2214 p.info.authority = p.info.authority + ";" + names[j];
2215 }
2216 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2217 Log.d(TAG, "Registered content provider: " + names[j] +
2218 ", className = " + p.info.name +
2219 ", isSyncable = " + p.info.isSyncable);
2220 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002221 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 Log.w(TAG, "Skipping provider name " + names[j] +
2223 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002224 "): name already used by "
2225 + ((other != null && other.component != null)
2226 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 }
2228 }
2229 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2230 if (r == null) {
2231 r = new StringBuilder(256);
2232 } else {
2233 r.append(' ');
2234 }
2235 r.append(p.info.name);
2236 }
2237 }
2238 if (r != null) {
2239 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2240 }
2241
2242 N = pkg.services.size();
2243 r = null;
2244 for (i=0; i<N; i++) {
2245 PackageParser.Service s = pkg.services.get(i);
2246 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2247 s.info.processName, pkg.applicationInfo.uid);
2248 mServices.addService(s);
2249 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2250 if (r == null) {
2251 r = new StringBuilder(256);
2252 } else {
2253 r.append(' ');
2254 }
2255 r.append(s.info.name);
2256 }
2257 }
2258 if (r != null) {
2259 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2260 }
2261
2262 N = pkg.receivers.size();
2263 r = null;
2264 for (i=0; i<N; i++) {
2265 PackageParser.Activity a = pkg.receivers.get(i);
2266 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2267 a.info.processName, pkg.applicationInfo.uid);
2268 mReceivers.addActivity(a, "receiver");
2269 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2270 if (r == null) {
2271 r = new StringBuilder(256);
2272 } else {
2273 r.append(' ');
2274 }
2275 r.append(a.info.name);
2276 }
2277 }
2278 if (r != null) {
2279 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2280 }
2281
2282 N = pkg.activities.size();
2283 r = null;
2284 for (i=0; i<N; i++) {
2285 PackageParser.Activity a = pkg.activities.get(i);
2286 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2287 a.info.processName, pkg.applicationInfo.uid);
2288 mActivities.addActivity(a, "activity");
2289 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2290 if (r == null) {
2291 r = new StringBuilder(256);
2292 } else {
2293 r.append(' ');
2294 }
2295 r.append(a.info.name);
2296 }
2297 }
2298 if (r != null) {
2299 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2300 }
2301
2302 N = pkg.permissionGroups.size();
2303 r = null;
2304 for (i=0; i<N; i++) {
2305 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2306 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2307 if (cur == null) {
2308 mPermissionGroups.put(pg.info.name, pg);
2309 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2310 if (r == null) {
2311 r = new StringBuilder(256);
2312 } else {
2313 r.append(' ');
2314 }
2315 r.append(pg.info.name);
2316 }
2317 } else {
2318 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2319 + pg.info.packageName + " ignored: original from "
2320 + cur.info.packageName);
2321 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2322 if (r == null) {
2323 r = new StringBuilder(256);
2324 } else {
2325 r.append(' ');
2326 }
2327 r.append("DUP:");
2328 r.append(pg.info.name);
2329 }
2330 }
2331 }
2332 if (r != null) {
2333 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2334 }
2335
2336 N = pkg.permissions.size();
2337 r = null;
2338 for (i=0; i<N; i++) {
2339 PackageParser.Permission p = pkg.permissions.get(i);
2340 HashMap<String, BasePermission> permissionMap =
2341 p.tree ? mSettings.mPermissionTrees
2342 : mSettings.mPermissions;
2343 p.group = mPermissionGroups.get(p.info.group);
2344 if (p.info.group == null || p.group != null) {
2345 BasePermission bp = permissionMap.get(p.info.name);
2346 if (bp == null) {
2347 bp = new BasePermission(p.info.name, p.info.packageName,
2348 BasePermission.TYPE_NORMAL);
2349 permissionMap.put(p.info.name, bp);
2350 }
2351 if (bp.perm == null) {
2352 if (bp.sourcePackage == null
2353 || bp.sourcePackage.equals(p.info.packageName)) {
2354 BasePermission tree = findPermissionTreeLP(p.info.name);
2355 if (tree == null
2356 || tree.sourcePackage.equals(p.info.packageName)) {
2357 bp.perm = p;
2358 bp.uid = pkg.applicationInfo.uid;
2359 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2360 if (r == null) {
2361 r = new StringBuilder(256);
2362 } else {
2363 r.append(' ');
2364 }
2365 r.append(p.info.name);
2366 }
2367 } else {
2368 Log.w(TAG, "Permission " + p.info.name + " from package "
2369 + p.info.packageName + " ignored: base tree "
2370 + tree.name + " is from package "
2371 + tree.sourcePackage);
2372 }
2373 } else {
2374 Log.w(TAG, "Permission " + p.info.name + " from package "
2375 + p.info.packageName + " ignored: original from "
2376 + bp.sourcePackage);
2377 }
2378 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2379 if (r == null) {
2380 r = new StringBuilder(256);
2381 } else {
2382 r.append(' ');
2383 }
2384 r.append("DUP:");
2385 r.append(p.info.name);
2386 }
2387 } else {
2388 Log.w(TAG, "Permission " + p.info.name + " from package "
2389 + p.info.packageName + " ignored: no group "
2390 + p.group);
2391 }
2392 }
2393 if (r != null) {
2394 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2395 }
2396
2397 N = pkg.instrumentation.size();
2398 r = null;
2399 for (i=0; i<N; i++) {
2400 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2401 a.info.packageName = pkg.applicationInfo.packageName;
2402 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2403 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2404 a.info.dataDir = pkg.applicationInfo.dataDir;
2405 mInstrumentation.put(a.component, a);
2406 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2407 if (r == null) {
2408 r = new StringBuilder(256);
2409 } else {
2410 r.append(' ');
2411 }
2412 r.append(a.info.name);
2413 }
2414 }
2415 if (r != null) {
2416 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2417 }
2418
2419 pkgSetting.setTimeStamp(scanFileTime);
2420 }
2421
2422 return pkg;
2423 }
2424
2425 private void cachePackageSharedLibsLI(PackageParser.Package pkg,
2426 File dataPath, File scanFile) throws IOException {
2427 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2428 final String sharedLibraryABI = "armeabi";
2429 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2430 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2431 final String sharedLibrarySuffix = ".so";
2432 boolean createdSharedLib = false;
2433 try {
2434 ZipFile zipFile = new ZipFile(scanFile);
2435 Enumeration<ZipEntry> entries =
2436 (Enumeration<ZipEntry>) zipFile.entries();
2437
2438 while (entries.hasMoreElements()) {
2439 ZipEntry entry = entries.nextElement();
2440 if (entry.isDirectory()) {
2441 continue;
2442 }
2443 String entryName = entry.getName();
2444 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2445 && entryName.endsWith(sharedLibrarySuffix))) {
2446 continue;
2447 }
2448 String libFileName = entryName.substring(
2449 apkLibraryDirectory.length());
2450 if (libFileName.contains("/")
2451 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2452 continue;
2453 }
2454 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2455 File.separator + libFileName;
2456 File sharedLibraryFile = new File(sharedLibraryFilePath);
2457 if (! sharedLibraryFile.exists() ||
2458 sharedLibraryFile.length() != entry.getSize() ||
2459 sharedLibraryFile.lastModified() != entry.getTime()) {
2460 if (Config.LOGD) {
2461 Log.d(TAG, "Caching shared lib " + entry.getName());
2462 }
2463 if (mInstaller == null) {
2464 sharedLibraryDir.mkdir();
2465 createdSharedLib = true;
2466 }
2467 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2468 sharedLibraryFile);
2469 }
2470 }
2471 } catch (IOException e) {
2472 Log.e(TAG, "Failed to cache package shared libs", e);
2473 if(createdSharedLib) {
2474 sharedLibraryDir.delete();
2475 }
2476 throw e;
2477 }
2478 }
2479
2480 private void cacheSharedLibLI(PackageParser.Package pkg,
2481 ZipFile zipFile, ZipEntry entry,
2482 File sharedLibraryDir,
2483 File sharedLibraryFile) throws IOException {
2484 InputStream inputStream = zipFile.getInputStream(entry);
2485 try {
2486 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2487 String tempFilePath = tempFile.getPath();
2488 // XXX package manager can't change owner, so the lib files for
2489 // now need to be left as world readable and owned by the system.
2490 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2491 ! tempFile.setLastModified(entry.getTime()) ||
2492 FileUtils.setPermissions(tempFilePath,
2493 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2494 |FileUtils.S_IROTH, -1, -1) != 0 ||
2495 ! tempFile.renameTo(sharedLibraryFile)) {
2496 // Failed to properly write file.
2497 tempFile.delete();
2498 throw new IOException("Couldn't create cached shared lib "
2499 + sharedLibraryFile + " in " + sharedLibraryDir);
2500 }
2501 } finally {
2502 inputStream.close();
2503 }
2504 }
2505
2506 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2507 if (chatty && Config.LOGD) Log.d(
2508 TAG, "Removing package " + pkg.applicationInfo.packageName );
2509
2510 synchronized (mPackages) {
2511 if (pkg.mPreferredOrder > 0) {
2512 mSettings.mPreferredPackages.remove(pkg);
2513 pkg.mPreferredOrder = 0;
2514 updatePreferredIndicesLP();
2515 }
2516
2517 clearPackagePreferredActivitiesLP(pkg.packageName);
2518
2519 mPackages.remove(pkg.applicationInfo.packageName);
2520 if (pkg.mPath != null) {
2521 mAppDirs.remove(pkg.mPath);
2522 }
2523
2524 PackageSetting ps = (PackageSetting)pkg.mExtras;
2525 if (ps != null && ps.sharedUser != null) {
2526 // XXX don't do this until the data is removed.
2527 if (false) {
2528 ps.sharedUser.packages.remove(ps);
2529 if (ps.sharedUser.packages.size() == 0) {
2530 // Remove.
2531 }
2532 }
2533 }
2534
2535 int N = pkg.providers.size();
2536 StringBuilder r = null;
2537 int i;
2538 for (i=0; i<N; i++) {
2539 PackageParser.Provider p = pkg.providers.get(i);
2540 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2541 p.info.name));
2542 if (p.info.authority == null) {
2543
2544 /* The is another ContentProvider with this authority when
2545 * this app was installed so this authority is null,
2546 * Ignore it as we don't have to unregister the provider.
2547 */
2548 continue;
2549 }
2550 String names[] = p.info.authority.split(";");
2551 for (int j = 0; j < names.length; j++) {
2552 if (mProviders.get(names[j]) == p) {
2553 mProviders.remove(names[j]);
2554 if (chatty && Config.LOGD) Log.d(
2555 TAG, "Unregistered content provider: " + names[j] +
2556 ", className = " + p.info.name +
2557 ", isSyncable = " + p.info.isSyncable);
2558 }
2559 }
2560 if (chatty) {
2561 if (r == null) {
2562 r = new StringBuilder(256);
2563 } else {
2564 r.append(' ');
2565 }
2566 r.append(p.info.name);
2567 }
2568 }
2569 if (r != null) {
2570 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2571 }
2572
2573 N = pkg.services.size();
2574 r = null;
2575 for (i=0; i<N; i++) {
2576 PackageParser.Service s = pkg.services.get(i);
2577 mServices.removeService(s);
2578 if (chatty) {
2579 if (r == null) {
2580 r = new StringBuilder(256);
2581 } else {
2582 r.append(' ');
2583 }
2584 r.append(s.info.name);
2585 }
2586 }
2587 if (r != null) {
2588 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2589 }
2590
2591 N = pkg.receivers.size();
2592 r = null;
2593 for (i=0; i<N; i++) {
2594 PackageParser.Activity a = pkg.receivers.get(i);
2595 mReceivers.removeActivity(a, "receiver");
2596 if (chatty) {
2597 if (r == null) {
2598 r = new StringBuilder(256);
2599 } else {
2600 r.append(' ');
2601 }
2602 r.append(a.info.name);
2603 }
2604 }
2605 if (r != null) {
2606 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2607 }
2608
2609 N = pkg.activities.size();
2610 r = null;
2611 for (i=0; i<N; i++) {
2612 PackageParser.Activity a = pkg.activities.get(i);
2613 mActivities.removeActivity(a, "activity");
2614 if (chatty) {
2615 if (r == null) {
2616 r = new StringBuilder(256);
2617 } else {
2618 r.append(' ');
2619 }
2620 r.append(a.info.name);
2621 }
2622 }
2623 if (r != null) {
2624 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2625 }
2626
2627 N = pkg.permissions.size();
2628 r = null;
2629 for (i=0; i<N; i++) {
2630 PackageParser.Permission p = pkg.permissions.get(i);
2631 boolean tree = false;
2632 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2633 if (bp == null) {
2634 tree = true;
2635 bp = mSettings.mPermissionTrees.get(p.info.name);
2636 }
2637 if (bp != null && bp.perm == p) {
2638 if (bp.type != BasePermission.TYPE_BUILTIN) {
2639 if (tree) {
2640 mSettings.mPermissionTrees.remove(p.info.name);
2641 } else {
2642 mSettings.mPermissions.remove(p.info.name);
2643 }
2644 } else {
2645 bp.perm = null;
2646 }
2647 if (chatty) {
2648 if (r == null) {
2649 r = new StringBuilder(256);
2650 } else {
2651 r.append(' ');
2652 }
2653 r.append(p.info.name);
2654 }
2655 }
2656 }
2657 if (r != null) {
2658 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2659 }
2660
2661 N = pkg.instrumentation.size();
2662 r = null;
2663 for (i=0; i<N; i++) {
2664 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2665 mInstrumentation.remove(a.component);
2666 if (chatty) {
2667 if (r == null) {
2668 r = new StringBuilder(256);
2669 } else {
2670 r.append(' ');
2671 }
2672 r.append(a.info.name);
2673 }
2674 }
2675 if (r != null) {
2676 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2677 }
2678 }
2679 }
2680
2681 private static final boolean isPackageFilename(String name) {
2682 return name != null && name.endsWith(".apk");
2683 }
2684
2685 private void updatePermissionsLP() {
2686 // Make sure there are no dangling permission trees.
2687 Iterator<BasePermission> it = mSettings.mPermissionTrees
2688 .values().iterator();
2689 while (it.hasNext()) {
2690 BasePermission bp = it.next();
2691 if (bp.perm == null) {
2692 Log.w(TAG, "Removing dangling permission tree: " + bp.name
2693 + " from package " + bp.sourcePackage);
2694 it.remove();
2695 }
2696 }
2697
2698 // Make sure all dynamic permissions have been assigned to a package,
2699 // and make sure there are no dangling permissions.
2700 it = mSettings.mPermissions.values().iterator();
2701 while (it.hasNext()) {
2702 BasePermission bp = it.next();
2703 if (bp.type == BasePermission.TYPE_DYNAMIC) {
2704 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
2705 + bp.name + " pkg=" + bp.sourcePackage
2706 + " info=" + bp.pendingInfo);
2707 if (bp.perm == null && bp.pendingInfo != null) {
2708 BasePermission tree = findPermissionTreeLP(bp.name);
2709 if (tree != null) {
2710 bp.perm = new PackageParser.Permission(tree.perm.owner,
2711 new PermissionInfo(bp.pendingInfo));
2712 bp.perm.info.packageName = tree.perm.info.packageName;
2713 bp.perm.info.name = bp.name;
2714 bp.uid = tree.uid;
2715 }
2716 }
2717 }
2718 if (bp.perm == null) {
2719 Log.w(TAG, "Removing dangling permission: " + bp.name
2720 + " from package " + bp.sourcePackage);
2721 it.remove();
2722 }
2723 }
2724
2725 // Now update the permissions for all packages, in particular
2726 // replace the granted permissions of the system packages.
2727 for (PackageParser.Package pkg : mPackages.values()) {
2728 grantPermissionsLP(pkg, false);
2729 }
2730 }
2731
2732 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
2733 final PackageSetting ps = (PackageSetting)pkg.mExtras;
2734 if (ps == null) {
2735 return;
2736 }
2737 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2738 boolean addedPermission = false;
2739
2740 if (replace) {
2741 ps.permissionsFixed = false;
2742 if (gp == ps) {
2743 gp.grantedPermissions.clear();
2744 gp.gids = mGlobalGids;
2745 }
2746 }
2747
2748 if (gp.gids == null) {
2749 gp.gids = mGlobalGids;
2750 }
2751
2752 final int N = pkg.requestedPermissions.size();
2753 for (int i=0; i<N; i++) {
2754 String name = pkg.requestedPermissions.get(i);
2755 BasePermission bp = mSettings.mPermissions.get(name);
2756 PackageParser.Permission p = bp != null ? bp.perm : null;
2757 if (false) {
2758 if (gp != ps) {
2759 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
2760 + ": " + p);
2761 }
2762 }
2763 if (p != null) {
2764 final String perm = p.info.name;
2765 boolean allowed;
2766 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
2767 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
2768 allowed = true;
2769 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
2770 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2771 allowed = (checkSignaturesLP(p.owner, pkg)
2772 == PackageManager.SIGNATURE_MATCH)
2773 || (checkSignaturesLP(mPlatformPackage, pkg)
2774 == PackageManager.SIGNATURE_MATCH);
2775 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2776 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
2777 // For updated system applications, the signatureOrSystem permission
2778 // is granted only if it had been defined by the original application.
2779 if ((pkg.applicationInfo.flags
2780 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
2781 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
2782 if(sysPs.grantedPermissions.contains(perm)) {
2783 allowed = true;
2784 } else {
2785 allowed = false;
2786 }
2787 } else {
2788 allowed = true;
2789 }
2790 }
2791 }
2792 } else {
2793 allowed = false;
2794 }
2795 if (false) {
2796 if (gp != ps) {
2797 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
2798 }
2799 }
2800 if (allowed) {
2801 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
2802 && ps.permissionsFixed) {
2803 // If this is an existing, non-system package, then
2804 // we can't add any new permissions to it.
2805 if (!gp.loadedPermissions.contains(perm)) {
2806 allowed = false;
2807 }
2808 }
2809 if (allowed) {
2810 if (!gp.grantedPermissions.contains(perm)) {
2811 addedPermission = true;
2812 gp.grantedPermissions.add(perm);
2813 gp.gids = appendInts(gp.gids, bp.gids);
2814 }
2815 } else {
2816 Log.w(TAG, "Not granting permission " + perm
2817 + " to package " + pkg.packageName
2818 + " because it was previously installed without");
2819 }
2820 } else {
2821 Log.w(TAG, "Not granting permission " + perm
2822 + " to package " + pkg.packageName
2823 + " (protectionLevel=" + p.info.protectionLevel
2824 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
2825 + ")");
2826 }
2827 } else {
2828 Log.w(TAG, "Unknown permission " + name
2829 + " in package " + pkg.packageName);
2830 }
2831 }
2832
2833 if ((addedPermission || replace) && !ps.permissionsFixed &&
2834 (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2835 // This is the first that we have heard about this package, so the
2836 // permissions we have now selected are fixed until explicitly
2837 // changed.
2838 ps.permissionsFixed = true;
2839 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
2840 }
2841 }
2842
2843 private final class ActivityIntentResolver
2844 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
2845 public List queryIntent(ContentResolver resolver, Intent intent,
2846 String resolvedType, boolean defaultOnly) {
2847 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2848 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2849 }
2850
2851 public List queryIntent(ContentResolver resolver, Intent intent,
2852 String resolvedType, int flags) {
2853 mFlags = flags;
2854 return super.queryIntent(
2855 resolver, intent, resolvedType,
2856 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2857 }
2858
2859 public final void addActivity(PackageParser.Activity a, String type) {
2860 mActivities.put(a.component, a);
2861 if (SHOW_INFO || Config.LOGV) Log.v(
2862 TAG, " " + type + " " +
2863 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2864 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2865 int NI = a.intents.size();
2866 int j;
2867 for (j=0; j<NI; j++) {
2868 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2869 if (SHOW_INFO || Config.LOGV) {
2870 Log.v(TAG, " IntentFilter:");
2871 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2872 }
2873 if (!intent.debugCheck()) {
2874 Log.w(TAG, "==> For Activity " + a.info.name);
2875 }
2876 addFilter(intent);
2877 }
2878 }
2879
2880 public final void removeActivity(PackageParser.Activity a, String type) {
2881 mActivities.remove(a.component);
2882 if (SHOW_INFO || Config.LOGV) Log.v(
2883 TAG, " " + type + " " +
2884 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2885 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2886 int NI = a.intents.size();
2887 int j;
2888 for (j=0; j<NI; j++) {
2889 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2890 if (SHOW_INFO || Config.LOGV) {
2891 Log.v(TAG, " IntentFilter:");
2892 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2893 }
2894 removeFilter(intent);
2895 }
2896 }
2897
2898 @Override
2899 protected boolean allowFilterResult(
2900 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
2901 ActivityInfo filterAi = filter.activity.info;
2902 for (int i=dest.size()-1; i>=0; i--) {
2903 ActivityInfo destAi = dest.get(i).activityInfo;
2904 if (destAi.name == filterAi.name
2905 && destAi.packageName == filterAi.packageName) {
2906 return false;
2907 }
2908 }
2909 return true;
2910 }
2911
2912 @Override
2913 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
2914 int match) {
2915 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
2916 return null;
2917 }
2918 final PackageParser.Activity activity = info.activity;
2919 if (mSafeMode && (activity.info.applicationInfo.flags
2920 &ApplicationInfo.FLAG_SYSTEM) == 0) {
2921 return null;
2922 }
2923 final ResolveInfo res = new ResolveInfo();
2924 res.activityInfo = PackageParser.generateActivityInfo(activity,
2925 mFlags);
2926 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
2927 res.filter = info;
2928 }
2929 res.priority = info.getPriority();
2930 res.preferredOrder = activity.owner.mPreferredOrder;
2931 //System.out.println("Result: " + res.activityInfo.className +
2932 // " = " + res.priority);
2933 res.match = match;
2934 res.isDefault = info.hasDefault;
2935 res.labelRes = info.labelRes;
2936 res.nonLocalizedLabel = info.nonLocalizedLabel;
2937 res.icon = info.icon;
2938 return res;
2939 }
2940
2941 @Override
2942 protected void sortResults(List<ResolveInfo> results) {
2943 Collections.sort(results, mResolvePrioritySorter);
2944 }
2945
2946 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002947 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002949 out.print(prefix); out.print(
2950 Integer.toHexString(System.identityHashCode(filter.activity)));
2951 out.print(' ');
2952 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
2954
2955// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
2956// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
2957// final List<ResolveInfo> retList = Lists.newArrayList();
2958// while (i.hasNext()) {
2959// final ResolveInfo resolveInfo = i.next();
2960// if (isEnabledLP(resolveInfo.activityInfo)) {
2961// retList.add(resolveInfo);
2962// }
2963// }
2964// return retList;
2965// }
2966
2967 // Keys are String (activity class name), values are Activity.
2968 private final HashMap<ComponentName, PackageParser.Activity> mActivities
2969 = new HashMap<ComponentName, PackageParser.Activity>();
2970 private int mFlags;
2971 }
2972
2973 private final class ServiceIntentResolver
2974 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
2975 public List queryIntent(ContentResolver resolver, Intent intent,
2976 String resolvedType, boolean defaultOnly) {
2977 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2978 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2979 }
2980
2981 public List queryIntent(ContentResolver resolver, Intent intent,
2982 String resolvedType, int flags) {
2983 mFlags = flags;
2984 return super.queryIntent(
2985 resolver, intent, resolvedType,
2986 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2987 }
2988
2989 public final void addService(PackageParser.Service s) {
2990 mServices.put(s.component, s);
2991 if (SHOW_INFO || Config.LOGV) Log.v(
2992 TAG, " " + (s.info.nonLocalizedLabel != null
2993 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2994 if (SHOW_INFO || Config.LOGV) Log.v(
2995 TAG, " Class=" + s.info.name);
2996 int NI = s.intents.size();
2997 int j;
2998 for (j=0; j<NI; j++) {
2999 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3000 if (SHOW_INFO || Config.LOGV) {
3001 Log.v(TAG, " IntentFilter:");
3002 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3003 }
3004 if (!intent.debugCheck()) {
3005 Log.w(TAG, "==> For Service " + s.info.name);
3006 }
3007 addFilter(intent);
3008 }
3009 }
3010
3011 public final void removeService(PackageParser.Service s) {
3012 mServices.remove(s.component);
3013 if (SHOW_INFO || Config.LOGV) Log.v(
3014 TAG, " " + (s.info.nonLocalizedLabel != null
3015 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3016 if (SHOW_INFO || Config.LOGV) Log.v(
3017 TAG, " Class=" + s.info.name);
3018 int NI = s.intents.size();
3019 int j;
3020 for (j=0; j<NI; j++) {
3021 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3022 if (SHOW_INFO || Config.LOGV) {
3023 Log.v(TAG, " IntentFilter:");
3024 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3025 }
3026 removeFilter(intent);
3027 }
3028 }
3029
3030 @Override
3031 protected boolean allowFilterResult(
3032 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3033 ServiceInfo filterSi = filter.service.info;
3034 for (int i=dest.size()-1; i>=0; i--) {
3035 ServiceInfo destAi = dest.get(i).serviceInfo;
3036 if (destAi.name == filterSi.name
3037 && destAi.packageName == filterSi.packageName) {
3038 return false;
3039 }
3040 }
3041 return true;
3042 }
3043
3044 @Override
3045 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3046 int match) {
3047 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3048 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3049 return null;
3050 }
3051 final PackageParser.Service service = info.service;
3052 if (mSafeMode && (service.info.applicationInfo.flags
3053 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3054 return null;
3055 }
3056 final ResolveInfo res = new ResolveInfo();
3057 res.serviceInfo = PackageParser.generateServiceInfo(service,
3058 mFlags);
3059 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3060 res.filter = filter;
3061 }
3062 res.priority = info.getPriority();
3063 res.preferredOrder = service.owner.mPreferredOrder;
3064 //System.out.println("Result: " + res.activityInfo.className +
3065 // " = " + res.priority);
3066 res.match = match;
3067 res.isDefault = info.hasDefault;
3068 res.labelRes = info.labelRes;
3069 res.nonLocalizedLabel = info.nonLocalizedLabel;
3070 res.icon = info.icon;
3071 return res;
3072 }
3073
3074 @Override
3075 protected void sortResults(List<ResolveInfo> results) {
3076 Collections.sort(results, mResolvePrioritySorter);
3077 }
3078
3079 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003080 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003082 out.print(prefix); out.print(
3083 Integer.toHexString(System.identityHashCode(filter.service)));
3084 out.print(' ');
3085 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 }
3087
3088// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3089// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3090// final List<ResolveInfo> retList = Lists.newArrayList();
3091// while (i.hasNext()) {
3092// final ResolveInfo resolveInfo = (ResolveInfo) i;
3093// if (isEnabledLP(resolveInfo.serviceInfo)) {
3094// retList.add(resolveInfo);
3095// }
3096// }
3097// return retList;
3098// }
3099
3100 // Keys are String (activity class name), values are Activity.
3101 private final HashMap<ComponentName, PackageParser.Service> mServices
3102 = new HashMap<ComponentName, PackageParser.Service>();
3103 private int mFlags;
3104 };
3105
3106 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3107 new Comparator<ResolveInfo>() {
3108 public int compare(ResolveInfo r1, ResolveInfo r2) {
3109 int v1 = r1.priority;
3110 int v2 = r2.priority;
3111 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3112 if (v1 != v2) {
3113 return (v1 > v2) ? -1 : 1;
3114 }
3115 v1 = r1.preferredOrder;
3116 v2 = r2.preferredOrder;
3117 if (v1 != v2) {
3118 return (v1 > v2) ? -1 : 1;
3119 }
3120 if (r1.isDefault != r2.isDefault) {
3121 return r1.isDefault ? -1 : 1;
3122 }
3123 v1 = r1.match;
3124 v2 = r2.match;
3125 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3126 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3127 }
3128 };
3129
3130 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3131 new Comparator<ProviderInfo>() {
3132 public int compare(ProviderInfo p1, ProviderInfo p2) {
3133 final int v1 = p1.initOrder;
3134 final int v2 = p2.initOrder;
3135 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3136 }
3137 };
3138
3139 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3140 IActivityManager am = ActivityManagerNative.getDefault();
3141 if (am != null) {
3142 try {
3143 final Intent intent = new Intent(action,
3144 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3145 if (extras != null) {
3146 intent.putExtras(extras);
3147 }
3148 am.broadcastIntent(
3149 null, intent,
3150 null, null, 0, null, null, null, false, false);
3151 } catch (RemoteException ex) {
3152 }
3153 }
3154 }
3155
3156 private final class AppDirObserver extends FileObserver {
3157 public AppDirObserver(String path, int mask, boolean isrom) {
3158 super(path, mask);
3159 mRootDir = path;
3160 mIsRom = isrom;
3161 }
3162
3163 public void onEvent(int event, String path) {
3164 String removedPackage = null;
3165 int removedUid = -1;
3166 String addedPackage = null;
3167 int addedUid = -1;
3168
3169 synchronized (mInstallLock) {
3170 String fullPathStr = null;
3171 File fullPath = null;
3172 if (path != null) {
3173 fullPath = new File(mRootDir, path);
3174 fullPathStr = fullPath.getPath();
3175 }
3176
3177 if (Config.LOGV) Log.v(
3178 TAG, "File " + fullPathStr + " changed: "
3179 + Integer.toHexString(event));
3180
3181 if (!isPackageFilename(path)) {
3182 if (Config.LOGV) Log.v(
3183 TAG, "Ignoring change of non-package file: " + fullPathStr);
3184 return;
3185 }
3186
3187 if ((event&REMOVE_EVENTS) != 0) {
3188 synchronized (mInstallLock) {
3189 PackageParser.Package p = mAppDirs.get(fullPathStr);
3190 if (p != null) {
3191 removePackageLI(p, true);
3192 removedPackage = p.applicationInfo.packageName;
3193 removedUid = p.applicationInfo.uid;
3194 }
3195 }
3196 }
3197
3198 if ((event&ADD_EVENTS) != 0) {
3199 PackageParser.Package p = mAppDirs.get(fullPathStr);
3200 if (p == null) {
3201 p = scanPackageLI(fullPath, fullPath, fullPath,
3202 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3203 PackageParser.PARSE_CHATTY |
3204 PackageParser.PARSE_MUST_BE_APK,
3205 SCAN_MONITOR);
3206 if (p != null) {
3207 synchronized (mPackages) {
3208 grantPermissionsLP(p, false);
3209 }
3210 addedPackage = p.applicationInfo.packageName;
3211 addedUid = p.applicationInfo.uid;
3212 }
3213 }
3214 }
3215
3216 synchronized (mPackages) {
3217 mSettings.writeLP();
3218 }
3219 }
3220
3221 if (removedPackage != null) {
3222 Bundle extras = new Bundle(1);
3223 extras.putInt(Intent.EXTRA_UID, removedUid);
3224 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3225 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3226 }
3227 if (addedPackage != null) {
3228 Bundle extras = new Bundle(1);
3229 extras.putInt(Intent.EXTRA_UID, addedUid);
3230 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3231 }
3232 }
3233
3234 private final String mRootDir;
3235 private final boolean mIsRom;
3236 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 /* Called when a downloaded package installation has been confirmed by the user */
3239 public void installPackage(
3240 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003241 installPackage(packageURI, observer, flags, null);
3242 }
3243
3244 /* Called when a downloaded package installation has been confirmed by the user */
3245 public void installPackage(
3246 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3247 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 mContext.enforceCallingOrSelfPermission(
3249 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 // Queue up an async operation since the package installation may take a little while.
3252 mHandler.post(new Runnable() {
3253 public void run() {
3254 mHandler.removeCallbacks(this);
3255 PackageInstalledInfo res;
3256 synchronized (mInstallLock) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003257 res = installPackageLI(packageURI, flags, true, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
3259 if (observer != null) {
3260 try {
3261 observer.packageInstalled(res.name, res.returnCode);
3262 } catch (RemoteException e) {
3263 Log.i(TAG, "Observer no longer exists.");
3264 }
3265 }
3266 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3267 // call appears in the synchronized block above.
3268 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3269 res.removedInfo.sendBroadcast(false, true);
3270 Bundle extras = new Bundle(1);
3271 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003272 final boolean update = res.removedInfo.removedPackage != null;
3273 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3275 }
3276 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3277 res.pkg.applicationInfo.packageName,
3278 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003279 if (update) {
3280 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3281 res.pkg.applicationInfo.packageName,
3282 extras);
3283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 }
3285 Runtime.getRuntime().gc();
3286 }
3287 });
3288 }
3289
3290 class PackageInstalledInfo {
3291 String name;
3292 int uid;
3293 PackageParser.Package pkg;
3294 int returnCode;
3295 PackageRemovedInfo removedInfo;
3296 }
3297
3298 /*
3299 * Install a non-existing package.
3300 */
3301 private void installNewPackageLI(String pkgName,
3302 File tmpPackageFile,
3303 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003304 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003305 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 // Remember this for later, in case we need to rollback this install
3307 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3308 res.name = pkgName;
3309 synchronized(mPackages) {
3310 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3311 // Don't allow installation over an existing package with the same name.
3312 Log.w(TAG, "Attempt to re-install " + pkgName
3313 + " without first uninstalling.");
3314 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3315 return;
3316 }
3317 }
3318 if (destPackageFile.exists()) {
3319 // It's safe to do this because we know (from the above check) that the file
3320 // isn't currently used for an installed package.
3321 destPackageFile.delete();
3322 }
3323 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3324 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3325 destResourceFile, pkg, 0,
3326 SCAN_MONITOR | SCAN_FORCE_DEX
3327 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003328 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3329 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 if (newPackage == null) {
3331 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3332 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3333 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3334 }
3335 } else {
3336 updateSettingsLI(pkgName, tmpPackageFile,
3337 destFilePath, destPackageFile,
3338 destResourceFile, pkg,
3339 newPackage,
3340 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003341 forwardLocked,
3342 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 res);
3344 // delete the partially installed application. the data directory will have to be
3345 // restored if it was already existing
3346 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3347 // remove package from internal structures. Note that we want deletePackageX to
3348 // delete the package data and cache directories that it created in
3349 // scanPackageLocked, unless those directories existed before we even tried to
3350 // install.
3351 deletePackageLI(
3352 pkgName, true,
3353 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3354 res.removedInfo);
3355 }
3356 }
3357 }
3358
3359 private void replacePackageLI(String pkgName,
3360 File tmpPackageFile,
3361 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003362 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003363 String installerPackageName, PackageInstalledInfo res) {
3364
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003365 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 // First find the old package info and check signatures
3367 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003368 oldPackage = mPackages.get(pkgName);
3369 if(checkSignaturesLP(pkg, oldPackage) != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3371 return;
3372 }
3373 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003374 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003376 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003378 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003379 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003381 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003382 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003383 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 }
3385 }
3386
3387 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3388 File tmpPackageFile,
3389 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003390 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003391 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 PackageParser.Package newPackage = null;
3393 String pkgName = deletedPackage.packageName;
3394 boolean deletedPkg = true;
3395 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003396
3397 String oldInstallerPackageName = null;
3398 synchronized (mPackages) {
3399 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3400 }
3401
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003402 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 // First delete the existing package while retaining the data directory
3404 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3405 res.removedInfo)) {
3406 // If the existing package was'nt successfully deleted
3407 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3408 deletedPkg = false;
3409 } else {
3410 // Successfully deleted the old package. Now proceed with re-installation
3411 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3412 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3413 destResourceFile, pkg, parseFlags,
3414 SCAN_MONITOR | SCAN_FORCE_DEX
3415 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003416 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3417 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 if (newPackage == null) {
3419 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3420 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3421 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3422 }
3423 } else {
3424 updateSettingsLI(pkgName, tmpPackageFile,
3425 destFilePath, destPackageFile,
3426 destResourceFile, pkg,
3427 newPackage,
3428 true,
3429 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003430 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 res);
3432 updatedSettings = true;
3433 }
3434 }
3435
3436 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3437 // If we deleted an exisiting package, the old source and resource files that we
3438 // were keeping around in case we needed them (see below) can now be deleted
3439 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3440 final ApplicationInfo installedPackageAppInfo =
3441 newPackage.applicationInfo;
3442 if (!deletedPackageAppInfo.sourceDir
3443 .equals(installedPackageAppInfo.sourceDir)) {
3444 new File(deletedPackageAppInfo.sourceDir).delete();
3445 }
3446 if (!deletedPackageAppInfo.publicSourceDir
3447 .equals(installedPackageAppInfo.publicSourceDir)) {
3448 new File(deletedPackageAppInfo.publicSourceDir).delete();
3449 }
3450 //update signature on the new package setting
3451 //this should always succeed, since we checked the
3452 //signature earlier.
3453 synchronized(mPackages) {
3454 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3455 parseFlags, true);
3456 }
3457 } else {
3458 // remove package from internal structures. Note that we want deletePackageX to
3459 // delete the package data and cache directories that it created in
3460 // scanPackageLocked, unless those directories existed before we even tried to
3461 // install.
3462 if(updatedSettings) {
3463 deletePackageLI(
3464 pkgName, true,
3465 PackageManager.DONT_DELETE_DATA,
3466 res.removedInfo);
3467 }
3468 // Since we failed to install the new package we need to restore the old
3469 // package that we deleted.
3470 if(deletedPkg) {
3471 installPackageLI(
3472 Uri.fromFile(new File(deletedPackage.mPath)),
3473 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003474 ? PackageManager.INSTALL_FORWARD_LOCK
Jacek Surazski65e13172009-04-28 15:26:38 +02003475 : 0, false, oldInstallerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 }
3477 }
3478 }
3479
3480 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3481 File tmpPackageFile,
3482 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003483 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003484 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 PackageParser.Package newPackage = null;
3486 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003487 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 PackageParser.PARSE_IS_SYSTEM;
3489 String packageName = deletedPackage.packageName;
3490 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3491 if (packageName == null) {
3492 Log.w(TAG, "Attempt to delete null packageName.");
3493 return;
3494 }
3495 PackageParser.Package oldPkg;
3496 PackageSetting oldPkgSetting;
3497 synchronized (mPackages) {
3498 oldPkg = mPackages.get(packageName);
3499 oldPkgSetting = mSettings.mPackages.get(packageName);
3500 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3501 (oldPkgSetting == null)) {
3502 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3503 return;
3504 }
3505 }
3506 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3507 res.removedInfo.removedPackage = packageName;
3508 // Remove existing system package
3509 removePackageLI(oldPkg, true);
3510 synchronized (mPackages) {
3511 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3512 }
3513
3514 // Successfully disabled the old package. Now proceed with re-installation
3515 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3516 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3517 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3518 destResourceFile, pkg, parseFlags,
3519 SCAN_MONITOR | SCAN_FORCE_DEX
3520 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003521 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3522 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 if (newPackage == null) {
3524 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3525 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3526 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3527 }
3528 } else {
3529 updateSettingsLI(packageName, tmpPackageFile,
3530 destFilePath, destPackageFile,
3531 destResourceFile, pkg,
3532 newPackage,
3533 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003534 forwardLocked,
3535 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 res);
3537 updatedSettings = true;
3538 }
3539
3540 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3541 //update signature on the new package setting
3542 //this should always succeed, since we checked the
3543 //signature earlier.
3544 synchronized(mPackages) {
3545 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3546 parseFlags, true);
3547 }
3548 } else {
3549 // Re installation failed. Restore old information
3550 // Remove new pkg information
3551 removePackageLI(newPackage, true);
3552 // Add back the old system package
3553 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3554 oldPkgSetting.resourcePath,
3555 oldPkg, parseFlags,
3556 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003557 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 // Restore the old system information in Settings
3559 synchronized(mPackages) {
3560 if(updatedSettings) {
3561 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02003562 mSettings.setInstallerPackageName(packageName,
3563 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 }
3565 mSettings.writeLP();
3566 }
3567 }
3568 }
3569
3570 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3571 String destFilePath, File destPackageFile,
3572 File destResourceFile,
3573 PackageParser.Package pkg,
3574 PackageParser.Package newPackage,
3575 boolean replacingExistingPackage,
3576 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003577 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 synchronized (mPackages) {
3579 //write settings. the installStatus will be incomplete at this stage.
3580 //note that the new package setting would have already been
3581 //added to mPackages. It hasn't been persisted yet.
3582 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3583 mSettings.writeLP();
3584 }
3585
3586 int retCode = 0;
3587 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3588 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3589 destPackageFile.toString());
3590 if (retCode != 0) {
3591 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3592 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3593 return;
3594 }
3595 }
3596 // XXX There are probably some big issues here: upon doing
3597 // the rename, we have reached the point of no return (the
3598 // original .apk is gone!), so we can't fail. Yet... we can.
3599 if (!tmpPackageFile.renameTo(destPackageFile)) {
3600 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3601 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3602 } else {
3603 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
3604 destResourceFile,
3605 forwardLocked);
3606 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3607 return;
3608 } else {
3609 Log.d(TAG, "New package installed in " + destPackageFile);
3610 }
3611 }
3612 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3613 if (mInstaller != null) {
3614 mInstaller.rmdex(tmpPackageFile.getPath());
3615 }
3616 }
3617
3618 synchronized (mPackages) {
3619 grantPermissionsLP(newPackage, true);
3620 res.name = pkgName;
3621 res.uid = newPackage.applicationInfo.uid;
3622 res.pkg = newPackage;
3623 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02003624 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3626 //to update install status
3627 mSettings.writeLP();
3628 }
3629 }
3630
The Android Open Source Project10592532009-03-18 17:39:46 -07003631 private PackageInstalledInfo installPackageLI(Uri pPackageURI,
Jacek Surazski65e13172009-04-28 15:26:38 +02003632 int pFlags, boolean newInstall, String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 File tmpPackageFile = null;
3634 String pkgName = null;
3635 boolean forwardLocked = false;
3636 boolean replacingExistingPackage = false;
3637 // Result object to be returned
3638 PackageInstalledInfo res = new PackageInstalledInfo();
3639 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3640 res.uid = -1;
3641 res.pkg = null;
3642 res.removedInfo = new PackageRemovedInfo();
3643
3644 main_flow: try {
3645 tmpPackageFile = createTempPackageFile();
3646 if (tmpPackageFile == null) {
3647 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3648 break main_flow;
3649 }
3650 tmpPackageFile.deleteOnExit(); // paranoia
3651 if (pPackageURI.getScheme().equals("file")) {
3652 final File srcPackageFile = new File(pPackageURI.getPath());
3653 // We copy the source package file to a temp file and then rename it to the
3654 // destination file in order to eliminate a window where the package directory
3655 // scanner notices the new package file but it's not completely copied yet.
3656 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3657 Log.e(TAG, "Couldn't copy package file to temp file.");
3658 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3659 break main_flow;
3660 }
3661 } else if (pPackageURI.getScheme().equals("content")) {
3662 ParcelFileDescriptor fd;
3663 try {
3664 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
3665 } catch (FileNotFoundException e) {
3666 Log.e(TAG, "Couldn't open file descriptor from download service.");
3667 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3668 break main_flow;
3669 }
3670 if (fd == null) {
3671 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3672 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3673 break main_flow;
3674 }
3675 if (Config.LOGV) {
3676 Log.v(TAG, "Opened file descriptor from download service.");
3677 }
3678 ParcelFileDescriptor.AutoCloseInputStream
3679 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3680 // We copy the source package file to a temp file and then rename it to the
3681 // destination file in order to eliminate a window where the package directory
3682 // scanner notices the new package file but it's not completely copied yet.
3683 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3684 Log.e(TAG, "Couldn't copy package stream to temp file.");
3685 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3686 break main_flow;
3687 }
3688 } else {
3689 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
3690 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3691 break main_flow;
3692 }
3693 pkgName = PackageParser.parsePackageName(
3694 tmpPackageFile.getAbsolutePath(), 0);
3695 if (pkgName == null) {
3696 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3697 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3698 break main_flow;
3699 }
3700 res.name = pkgName;
3701 //initialize some variables before installing pkg
3702 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003703 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 ? mDrmAppPrivateInstallDir
3705 : mAppInstallDir;
3706 final File destPackageFile = new File(destDir, pkgFileName);
3707 final String destFilePath = destPackageFile.getAbsolutePath();
3708 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003709 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 final String publicZipFileName = pkgName + ".zip";
3711 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3712 forwardLocked = true;
3713 } else {
3714 destResourceFile = destPackageFile;
3715 }
3716 // Retrieve PackageSettings and parse package
3717 int parseFlags = PackageParser.PARSE_CHATTY;
3718 parseFlags |= mDefParseFlags;
3719 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3720 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07003721 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3723 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3724 if (pkg == null) {
3725 res.returnCode = pp.getParseError();
3726 break main_flow;
3727 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003728 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
3729 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
3730 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
3731 break main_flow;
3732 }
3733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3735 res.returnCode = pp.getParseError();
3736 break main_flow;
3737 }
3738
3739 synchronized (mPackages) {
3740 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003741 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 && mPackages.containsKey(pkgName)) {
3743 replacingExistingPackage = true;
3744 }
3745 }
3746
3747 if(replacingExistingPackage) {
3748 replacePackageLI(pkgName,
3749 tmpPackageFile,
3750 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02003751 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 res);
3753 } else {
3754 installNewPackageLI(pkgName,
3755 tmpPackageFile,
3756 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02003757 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 res);
3759 }
3760 } finally {
3761 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3762 tmpPackageFile.delete();
3763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003765 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 }
3767
3768 private int setPermissionsLI(String pkgName,
3769 PackageParser.Package newPackage,
3770 String destFilePath,
3771 File destResourceFile,
3772 boolean forwardLocked) {
3773 int retCode;
3774 if (forwardLocked) {
3775 try {
3776 extractPublicFiles(newPackage, destResourceFile);
3777 } catch (IOException e) {
3778 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3779 " forward-locked app.");
3780 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3781 } finally {
3782 //TODO clean up the extracted public files
3783 }
3784 if (mInstaller != null) {
3785 retCode = mInstaller.setForwardLockPerm(pkgName,
3786 newPackage.applicationInfo.uid);
3787 } else {
3788 final int filePermissions =
3789 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3790 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3791 newPackage.applicationInfo.uid);
3792 }
3793 } else {
3794 final int filePermissions =
3795 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3796 |FileUtils.S_IROTH;
3797 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3798 }
3799 if (retCode != 0) {
3800 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3801 + ". The return code was: " + retCode);
3802 }
3803 return PackageManager.INSTALL_SUCCEEDED;
3804 }
3805
3806 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3807 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3808 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3809 }
3810
3811 private void extractPublicFiles(PackageParser.Package newPackage,
3812 File publicZipFile) throws IOException {
3813 final ZipOutputStream publicZipOutStream =
3814 new ZipOutputStream(new FileOutputStream(publicZipFile));
3815 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3816
3817 // Copy manifest, resources.arsc and res directory to public zip
3818
3819 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3820 while (privateZipEntries.hasMoreElements()) {
3821 final ZipEntry zipEntry = privateZipEntries.nextElement();
3822 final String zipEntryName = zipEntry.getName();
3823 if ("AndroidManifest.xml".equals(zipEntryName)
3824 || "resources.arsc".equals(zipEntryName)
3825 || zipEntryName.startsWith("res/")) {
3826 try {
3827 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3828 } catch (IOException e) {
3829 try {
3830 publicZipOutStream.close();
3831 throw e;
3832 } finally {
3833 publicZipFile.delete();
3834 }
3835 }
3836 }
3837 }
3838
3839 publicZipOutStream.close();
3840 FileUtils.setPermissions(
3841 publicZipFile.getAbsolutePath(),
3842 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
3843 -1, -1);
3844 }
3845
3846 private static void copyZipEntry(ZipEntry zipEntry,
3847 ZipFile inZipFile,
3848 ZipOutputStream outZipStream) throws IOException {
3849 byte[] buffer = new byte[4096];
3850 int num;
3851
3852 ZipEntry newEntry;
3853 if (zipEntry.getMethod() == ZipEntry.STORED) {
3854 // Preserve the STORED method of the input entry.
3855 newEntry = new ZipEntry(zipEntry);
3856 } else {
3857 // Create a new entry so that the compressed len is recomputed.
3858 newEntry = new ZipEntry(zipEntry.getName());
3859 }
3860 outZipStream.putNextEntry(newEntry);
3861
3862 InputStream data = inZipFile.getInputStream(zipEntry);
3863 while ((num = data.read(buffer)) > 0) {
3864 outZipStream.write(buffer, 0, num);
3865 }
3866 outZipStream.flush();
3867 }
3868
3869 private void deleteTempPackageFiles() {
3870 FilenameFilter filter = new FilenameFilter() {
3871 public boolean accept(File dir, String name) {
3872 return name.startsWith("vmdl") && name.endsWith(".tmp");
3873 }
3874 };
3875 String tmpFilesList[] = mAppInstallDir.list(filter);
3876 if(tmpFilesList == null) {
3877 return;
3878 }
3879 for(int i = 0; i < tmpFilesList.length; i++) {
3880 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
3881 tmpFile.delete();
3882 }
3883 }
3884
3885 private File createTempPackageFile() {
3886 File tmpPackageFile;
3887 try {
3888 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
3889 } catch (IOException e) {
3890 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
3891 return null;
3892 }
3893 try {
3894 FileUtils.setPermissions(
3895 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
3896 -1, -1);
3897 } catch (IOException e) {
3898 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
3899 return null;
3900 }
3901 return tmpPackageFile;
3902 }
3903
3904 public void deletePackage(final String packageName,
3905 final IPackageDeleteObserver observer,
3906 final int flags) {
3907 mContext.enforceCallingOrSelfPermission(
3908 android.Manifest.permission.DELETE_PACKAGES, null);
3909 // Queue up an async operation since the package deletion may take a little while.
3910 mHandler.post(new Runnable() {
3911 public void run() {
3912 mHandler.removeCallbacks(this);
3913 final boolean succeded = deletePackageX(packageName, true, true, flags);
3914 if (observer != null) {
3915 try {
3916 observer.packageDeleted(succeded);
3917 } catch (RemoteException e) {
3918 Log.i(TAG, "Observer no longer exists.");
3919 } //end catch
3920 } //end if
3921 } //end run
3922 });
3923 }
3924
3925 /**
3926 * This method is an internal method that could be get invoked either
3927 * to delete an installed package or to clean up a failed installation.
3928 * After deleting an installed package, a broadcast is sent to notify any
3929 * listeners that the package has been installed. For cleaning up a failed
3930 * installation, the broadcast is not necessary since the package's
3931 * installation wouldn't have sent the initial broadcast either
3932 * The key steps in deleting a package are
3933 * deleting the package information in internal structures like mPackages,
3934 * deleting the packages base directories through installd
3935 * updating mSettings to reflect current status
3936 * persisting settings for later use
3937 * sending a broadcast if necessary
3938 */
3939
3940 private boolean deletePackageX(String packageName, boolean sendBroadCast,
3941 boolean deleteCodeAndResources, int flags) {
3942 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07003943 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944
3945 synchronized (mInstallLock) {
3946 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
3947 }
3948
3949 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07003950 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
3951 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
3952
3953 // If the removed package was a system update, the old system packaged
3954 // was re-enabled; we need to broadcast this information
3955 if (systemUpdate) {
3956 Bundle extras = new Bundle(1);
3957 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
3958 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3959
3960 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
3961 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
3962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 }
3964 return res;
3965 }
3966
3967 static class PackageRemovedInfo {
3968 String removedPackage;
3969 int uid = -1;
3970 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07003971 boolean isRemovedPackageSystemUpdate = false;
3972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 void sendBroadcast(boolean fullRemove, boolean replacing) {
3974 Bundle extras = new Bundle(1);
3975 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
3976 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
3977 if (replacing) {
3978 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3979 }
3980 if (removedPackage != null) {
3981 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3982 }
3983 if (removedUid >= 0) {
3984 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
3985 }
3986 }
3987 }
3988
3989 /*
3990 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
3991 * flag is not set, the data directory is removed as well.
3992 * make sure this flag is set for partially installed apps. If not its meaningless to
3993 * delete a partially installed application.
3994 */
3995 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
3996 int flags) {
3997 String packageName = p.packageName;
3998 outInfo.removedPackage = packageName;
3999 removePackageLI(p, true);
4000 // Retrieve object to delete permissions for shared user later on
4001 PackageSetting deletedPs;
4002 synchronized (mPackages) {
4003 deletedPs = mSettings.mPackages.get(packageName);
4004 }
4005 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4006 if (mInstaller != null) {
4007 int retCode = mInstaller.remove(packageName);
4008 if (retCode < 0) {
4009 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4010 + packageName + ", retcode=" + retCode);
4011 // we don't consider this to be a failure of the core package deletion
4012 }
4013 } else {
4014 //for emulator
4015 PackageParser.Package pkg = mPackages.get(packageName);
4016 File dataDir = new File(pkg.applicationInfo.dataDir);
4017 dataDir.delete();
4018 }
4019 synchronized (mPackages) {
4020 outInfo.removedUid = mSettings.removePackageLP(packageName);
4021 }
4022 }
4023 synchronized (mPackages) {
4024 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4025 // remove permissions associated with package
4026 mSettings.updateSharedUserPerms (deletedPs);
4027 }
4028 // Save settings now
4029 mSettings.writeLP ();
4030 }
4031 }
4032
4033 /*
4034 * Tries to delete system package.
4035 */
4036 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004037 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 ApplicationInfo applicationInfo = p.applicationInfo;
4039 //applicable for non-partially installed applications only
4040 if (applicationInfo == null) {
4041 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4042 return false;
4043 }
4044 PackageSetting ps = null;
4045 // Confirm if the system package has been updated
4046 // An updated system app can be deleted. This will also have to restore
4047 // the system pkg from system partition
4048 synchronized (mPackages) {
4049 ps = mSettings.getDisabledSystemPkg(p.packageName);
4050 }
4051 if (ps == null) {
4052 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4053 return false;
4054 } else {
4055 Log.i(TAG, "Deleting system pkg from data partition");
4056 }
4057 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004058 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004059 boolean deleteCodeAndResources = false;
4060 if (ps.versionCode < p.mVersionCode) {
4061 // Delete code and resources for downgrades
4062 deleteCodeAndResources = true;
4063 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4064 flags &= ~PackageManager.DONT_DELETE_DATA;
4065 }
4066 } else {
4067 // Preserve data by setting flag
4068 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4069 flags |= PackageManager.DONT_DELETE_DATA;
4070 }
4071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4073 if (!ret) {
4074 return false;
4075 }
4076 synchronized (mPackages) {
4077 // Reinstate the old system package
4078 mSettings.enableSystemPackageLP(p.packageName);
4079 }
4080 // Install the system package
4081 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4082 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4083 SCAN_MONITOR);
4084
4085 if (newPkg == null) {
4086 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4087 return false;
4088 }
4089 synchronized (mPackages) {
4090 mSettings.writeLP();
4091 }
4092 return true;
4093 }
4094
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004095 private void deletePackageResourcesLI(String packageName,
4096 String sourceDir, String publicSourceDir) {
4097 File sourceFile = new File(sourceDir);
4098 if (!sourceFile.exists()) {
4099 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4100 }
4101 // Delete application's code and resources
4102 sourceFile.delete();
4103 final File publicSourceFile = new File(publicSourceDir);
4104 if (publicSourceFile.exists()) {
4105 publicSourceFile.delete();
4106 }
4107 if (mInstaller != null) {
4108 int retCode = mInstaller.rmdex(sourceFile.toString());
4109 if (retCode < 0) {
4110 Log.w(TAG, "Couldn't remove dex file for package: "
4111 + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4112 // we don't consider this to be a failure of the core package deletion
4113 }
4114 }
4115 }
4116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4118 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4119 ApplicationInfo applicationInfo = p.applicationInfo;
4120 if (applicationInfo == null) {
4121 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4122 return false;
4123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 outInfo.uid = applicationInfo.uid;
4125
4126 // Delete package data from internal structures and also remove data if flag is set
4127 removePackageDataLI(p, outInfo, flags);
4128
4129 // Delete application code and resources
4130 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004131 deletePackageResourcesLI(applicationInfo.packageName,
4132 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 }
4134 return true;
4135 }
4136
4137 /*
4138 * This method handles package deletion in general
4139 */
4140 private boolean deletePackageLI(String packageName,
4141 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4142 if (packageName == null) {
4143 Log.w(TAG, "Attempt to delete null packageName.");
4144 return false;
4145 }
4146 PackageParser.Package p;
4147 boolean dataOnly = false;
4148 synchronized (mPackages) {
4149 p = mPackages.get(packageName);
4150 if (p == null) {
4151 //this retrieves partially installed apps
4152 dataOnly = true;
4153 PackageSetting ps = mSettings.mPackages.get(packageName);
4154 if (ps == null) {
4155 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4156 return false;
4157 }
4158 p = ps.pkg;
4159 }
4160 }
4161 if (p == null) {
4162 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4163 return false;
4164 }
4165
4166 if (dataOnly) {
4167 // Delete application data first
4168 removePackageDataLI(p, outInfo, flags);
4169 return true;
4170 }
4171 // At this point the package should have ApplicationInfo associated with it
4172 if (p.applicationInfo == null) {
4173 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4174 return false;
4175 }
4176 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4177 Log.i(TAG, "Removing system package:"+p.packageName);
4178 // When an updated system application is deleted we delete the existing resources as well and
4179 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004180 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 }
4182 Log.i(TAG, "Removing non-system package:"+p.packageName);
4183 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4184 }
4185
4186 public void clearApplicationUserData(final String packageName,
4187 final IPackageDataObserver observer) {
4188 mContext.enforceCallingOrSelfPermission(
4189 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4190 // Queue up an async operation since the package deletion may take a little while.
4191 mHandler.post(new Runnable() {
4192 public void run() {
4193 mHandler.removeCallbacks(this);
4194 final boolean succeeded;
4195 synchronized (mInstallLock) {
4196 succeeded = clearApplicationUserDataLI(packageName);
4197 }
4198 if (succeeded) {
4199 // invoke DeviceStorageMonitor's update method to clear any notifications
4200 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4201 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4202 if (dsm != null) {
4203 dsm.updateMemory();
4204 }
4205 }
4206 if(observer != null) {
4207 try {
4208 observer.onRemoveCompleted(packageName, succeeded);
4209 } catch (RemoteException e) {
4210 Log.i(TAG, "Observer no longer exists.");
4211 }
4212 } //end if observer
4213 } //end run
4214 });
4215 }
4216
4217 private boolean clearApplicationUserDataLI(String packageName) {
4218 if (packageName == null) {
4219 Log.w(TAG, "Attempt to delete null packageName.");
4220 return false;
4221 }
4222 PackageParser.Package p;
4223 boolean dataOnly = false;
4224 synchronized (mPackages) {
4225 p = mPackages.get(packageName);
4226 if(p == null) {
4227 dataOnly = true;
4228 PackageSetting ps = mSettings.mPackages.get(packageName);
4229 if((ps == null) || (ps.pkg == null)) {
4230 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4231 return false;
4232 }
4233 p = ps.pkg;
4234 }
4235 }
4236 if(!dataOnly) {
4237 //need to check this only for fully installed applications
4238 if (p == null) {
4239 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4240 return false;
4241 }
4242 final ApplicationInfo applicationInfo = p.applicationInfo;
4243 if (applicationInfo == null) {
4244 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4245 return false;
4246 }
4247 }
4248 if (mInstaller != null) {
4249 int retCode = mInstaller.clearUserData(packageName);
4250 if (retCode < 0) {
4251 Log.w(TAG, "Couldn't remove cache files for package: "
4252 + packageName);
4253 return false;
4254 }
4255 }
4256 return true;
4257 }
4258
4259 public void deleteApplicationCacheFiles(final String packageName,
4260 final IPackageDataObserver observer) {
4261 mContext.enforceCallingOrSelfPermission(
4262 android.Manifest.permission.DELETE_CACHE_FILES, null);
4263 // Queue up an async operation since the package deletion may take a little while.
4264 mHandler.post(new Runnable() {
4265 public void run() {
4266 mHandler.removeCallbacks(this);
4267 final boolean succeded;
4268 synchronized (mInstallLock) {
4269 succeded = deleteApplicationCacheFilesLI(packageName);
4270 }
4271 if(observer != null) {
4272 try {
4273 observer.onRemoveCompleted(packageName, succeded);
4274 } catch (RemoteException e) {
4275 Log.i(TAG, "Observer no longer exists.");
4276 }
4277 } //end if observer
4278 } //end run
4279 });
4280 }
4281
4282 private boolean deleteApplicationCacheFilesLI(String packageName) {
4283 if (packageName == null) {
4284 Log.w(TAG, "Attempt to delete null packageName.");
4285 return false;
4286 }
4287 PackageParser.Package p;
4288 synchronized (mPackages) {
4289 p = mPackages.get(packageName);
4290 }
4291 if (p == null) {
4292 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4293 return false;
4294 }
4295 final ApplicationInfo applicationInfo = p.applicationInfo;
4296 if (applicationInfo == null) {
4297 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4298 return false;
4299 }
4300 if (mInstaller != null) {
4301 int retCode = mInstaller.deleteCacheFiles(packageName);
4302 if (retCode < 0) {
4303 Log.w(TAG, "Couldn't remove cache files for package: "
4304 + packageName);
4305 return false;
4306 }
4307 }
4308 return true;
4309 }
4310
4311 public void getPackageSizeInfo(final String packageName,
4312 final IPackageStatsObserver observer) {
4313 mContext.enforceCallingOrSelfPermission(
4314 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4315 // Queue up an async operation since the package deletion may take a little while.
4316 mHandler.post(new Runnable() {
4317 public void run() {
4318 mHandler.removeCallbacks(this);
4319 PackageStats lStats = new PackageStats(packageName);
4320 final boolean succeded;
4321 synchronized (mInstallLock) {
4322 succeded = getPackageSizeInfoLI(packageName, lStats);
4323 }
4324 if(observer != null) {
4325 try {
4326 observer.onGetStatsCompleted(lStats, succeded);
4327 } catch (RemoteException e) {
4328 Log.i(TAG, "Observer no longer exists.");
4329 }
4330 } //end if observer
4331 } //end run
4332 });
4333 }
4334
4335 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4336 if (packageName == null) {
4337 Log.w(TAG, "Attempt to get size of null packageName.");
4338 return false;
4339 }
4340 PackageParser.Package p;
4341 boolean dataOnly = false;
4342 synchronized (mPackages) {
4343 p = mPackages.get(packageName);
4344 if(p == null) {
4345 dataOnly = true;
4346 PackageSetting ps = mSettings.mPackages.get(packageName);
4347 if((ps == null) || (ps.pkg == null)) {
4348 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4349 return false;
4350 }
4351 p = ps.pkg;
4352 }
4353 }
4354 String publicSrcDir = null;
4355 if(!dataOnly) {
4356 final ApplicationInfo applicationInfo = p.applicationInfo;
4357 if (applicationInfo == null) {
4358 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4359 return false;
4360 }
4361 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4362 }
4363 if (mInstaller != null) {
4364 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4365 publicSrcDir, pStats);
4366 if (res < 0) {
4367 return false;
4368 } else {
4369 return true;
4370 }
4371 }
4372 return true;
4373 }
4374
4375
4376 public void addPackageToPreferred(String packageName) {
4377 mContext.enforceCallingOrSelfPermission(
4378 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4379
4380 synchronized (mPackages) {
4381 PackageParser.Package p = mPackages.get(packageName);
4382 if (p == null) {
4383 return;
4384 }
4385 PackageSetting ps = (PackageSetting)p.mExtras;
4386 if (ps != null) {
4387 mSettings.mPreferredPackages.remove(ps);
4388 mSettings.mPreferredPackages.add(0, ps);
4389 updatePreferredIndicesLP();
4390 mSettings.writeLP();
4391 }
4392 }
4393 }
4394
4395 public void removePackageFromPreferred(String packageName) {
4396 mContext.enforceCallingOrSelfPermission(
4397 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4398
4399 synchronized (mPackages) {
4400 PackageParser.Package p = mPackages.get(packageName);
4401 if (p == null) {
4402 return;
4403 }
4404 if (p.mPreferredOrder > 0) {
4405 PackageSetting ps = (PackageSetting)p.mExtras;
4406 if (ps != null) {
4407 mSettings.mPreferredPackages.remove(ps);
4408 p.mPreferredOrder = 0;
4409 updatePreferredIndicesLP();
4410 mSettings.writeLP();
4411 }
4412 }
4413 }
4414 }
4415
4416 private void updatePreferredIndicesLP() {
4417 final ArrayList<PackageSetting> pkgs
4418 = mSettings.mPreferredPackages;
4419 final int N = pkgs.size();
4420 for (int i=0; i<N; i++) {
4421 pkgs.get(i).pkg.mPreferredOrder = N - i;
4422 }
4423 }
4424
4425 public List<PackageInfo> getPreferredPackages(int flags) {
4426 synchronized (mPackages) {
4427 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4428 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4429 final int N = pref.size();
4430 for (int i=0; i<N; i++) {
4431 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4432 }
4433 return res;
4434 }
4435 }
4436
4437 public void addPreferredActivity(IntentFilter filter, int match,
4438 ComponentName[] set, ComponentName activity) {
4439 mContext.enforceCallingOrSelfPermission(
4440 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4441
4442 synchronized (mPackages) {
4443 Log.i(TAG, "Adding preferred activity " + activity + ":");
4444 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4445 mSettings.mPreferredActivities.addFilter(
4446 new PreferredActivity(filter, match, set, activity));
4447 mSettings.writeLP();
4448 }
4449 }
4450
4451 public void clearPackagePreferredActivities(String packageName) {
4452 mContext.enforceCallingOrSelfPermission(
4453 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4454
4455 synchronized (mPackages) {
4456 if (clearPackagePreferredActivitiesLP(packageName)) {
4457 mSettings.writeLP();
4458 }
4459 }
4460 }
4461
4462 boolean clearPackagePreferredActivitiesLP(String packageName) {
4463 boolean changed = false;
4464 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4465 while (it.hasNext()) {
4466 PreferredActivity pa = it.next();
4467 if (pa.mActivity.getPackageName().equals(packageName)) {
4468 it.remove();
4469 changed = true;
4470 }
4471 }
4472 return changed;
4473 }
4474
4475 public int getPreferredActivities(List<IntentFilter> outFilters,
4476 List<ComponentName> outActivities, String packageName) {
4477
4478 int num = 0;
4479 synchronized (mPackages) {
4480 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4481 while (it.hasNext()) {
4482 PreferredActivity pa = it.next();
4483 if (packageName == null
4484 || pa.mActivity.getPackageName().equals(packageName)) {
4485 if (outFilters != null) {
4486 outFilters.add(new IntentFilter(pa));
4487 }
4488 if (outActivities != null) {
4489 outActivities.add(pa.mActivity);
4490 }
4491 }
4492 }
4493 }
4494
4495 return num;
4496 }
4497
4498 public void setApplicationEnabledSetting(String appPackageName,
4499 int newState, int flags) {
4500 setEnabledSetting(appPackageName, null, newState, flags);
4501 }
4502
4503 public void setComponentEnabledSetting(ComponentName componentName,
4504 int newState, int flags) {
4505 setEnabledSetting(componentName.getPackageName(),
4506 componentName.getClassName(), newState, flags);
4507 }
4508
4509 private void setEnabledSetting(
4510 final String packageNameStr, String classNameStr, int newState, final int flags) {
4511 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4512 || newState == COMPONENT_ENABLED_STATE_ENABLED
4513 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4514 throw new IllegalArgumentException("Invalid new component state: "
4515 + newState);
4516 }
4517 PackageSetting pkgSetting;
4518 final int uid = Binder.getCallingUid();
4519 final int permission = mContext.checkCallingPermission(
4520 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4521 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4522 int packageUid = -1;
4523 synchronized (mPackages) {
4524 pkgSetting = mSettings.mPackages.get(packageNameStr);
4525 if (pkgSetting == null) {
4526 if (classNameStr == null) {
4527 throw new IllegalArgumentException(
4528 "Unknown package: " + packageNameStr);
4529 }
4530 throw new IllegalArgumentException(
4531 "Unknown component: " + packageNameStr
4532 + "/" + classNameStr);
4533 }
4534 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4535 throw new SecurityException(
4536 "Permission Denial: attempt to change component state from pid="
4537 + Binder.getCallingPid()
4538 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4539 }
4540 packageUid = pkgSetting.userId;
4541 if (classNameStr == null) {
4542 // We're dealing with an application/package level state change
4543 pkgSetting.enabled = newState;
4544 } else {
4545 // We're dealing with a component level state change
4546 switch (newState) {
4547 case COMPONENT_ENABLED_STATE_ENABLED:
4548 pkgSetting.enableComponentLP(classNameStr);
4549 break;
4550 case COMPONENT_ENABLED_STATE_DISABLED:
4551 pkgSetting.disableComponentLP(classNameStr);
4552 break;
4553 case COMPONENT_ENABLED_STATE_DEFAULT:
4554 pkgSetting.restoreComponentLP(classNameStr);
4555 break;
4556 default:
4557 Log.e(TAG, "Invalid new component state: " + newState);
4558 }
4559 }
4560 mSettings.writeLP();
4561 }
4562
4563 long callingId = Binder.clearCallingIdentity();
4564 try {
4565 Bundle extras = new Bundle(2);
4566 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
4567 (flags&PackageManager.DONT_KILL_APP) != 0);
4568 extras.putInt(Intent.EXTRA_UID, packageUid);
4569 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
4570 } finally {
4571 Binder.restoreCallingIdentity(callingId);
4572 }
4573 }
4574
Jacek Surazski65e13172009-04-28 15:26:38 +02004575 public String getInstallerPackageName(String packageName) {
4576 synchronized (mPackages) {
4577 PackageSetting pkg = mSettings.mPackages.get(packageName);
4578 if (pkg == null) {
4579 throw new IllegalArgumentException("Unknown package: " + packageName);
4580 }
4581 return pkg.installerPackageName;
4582 }
4583 }
4584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 public int getApplicationEnabledSetting(String appPackageName) {
4586 synchronized (mPackages) {
4587 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
4588 if (pkg == null) {
4589 throw new IllegalArgumentException("Unknown package: " + appPackageName);
4590 }
4591 return pkg.enabled;
4592 }
4593 }
4594
4595 public int getComponentEnabledSetting(ComponentName componentName) {
4596 synchronized (mPackages) {
4597 final String packageNameStr = componentName.getPackageName();
4598 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
4599 if (pkg == null) {
4600 throw new IllegalArgumentException("Unknown component: " + componentName);
4601 }
4602 final String classNameStr = componentName.getClassName();
4603 return pkg.currentEnabledStateLP(classNameStr);
4604 }
4605 }
4606
4607 public void enterSafeMode() {
4608 if (!mSystemReady) {
4609 mSafeMode = true;
4610 }
4611 }
4612
4613 public void systemReady() {
4614 mSystemReady = true;
4615 }
4616
4617 public boolean isSafeMode() {
4618 return mSafeMode;
4619 }
4620
4621 public boolean hasSystemUidErrors() {
4622 return mHasSystemUidErrors;
4623 }
4624
4625 static String arrayToString(int[] array) {
4626 StringBuffer buf = new StringBuffer(128);
4627 buf.append('[');
4628 if (array != null) {
4629 for (int i=0; i<array.length; i++) {
4630 if (i > 0) buf.append(", ");
4631 buf.append(array[i]);
4632 }
4633 }
4634 buf.append(']');
4635 return buf.toString();
4636 }
4637
4638 @Override
4639 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4640 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4641 != PackageManager.PERMISSION_GRANTED) {
4642 pw.println("Permission Denial: can't dump ActivityManager from from pid="
4643 + Binder.getCallingPid()
4644 + ", uid=" + Binder.getCallingUid()
4645 + " without permission "
4646 + android.Manifest.permission.DUMP);
4647 return;
4648 }
4649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 synchronized (mPackages) {
4651 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004652 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 pw.println(" ");
4654 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004655 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 pw.println(" ");
4657 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004658 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 pw.println(" ");
4660 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004661 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 pw.println(" ");
4663 pw.println("Preferred Packages:");
4664 {
4665 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004666 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 }
4668 }
4669 pw.println(" ");
4670 pw.println("Permissions:");
4671 {
4672 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004673 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
4674 pw.print(Integer.toHexString(System.identityHashCode(p)));
4675 pw.println("):");
4676 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
4677 pw.print(" uid="); pw.print(p.uid);
4678 pw.print(" gids="); pw.print(arrayToString(p.gids));
4679 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 }
4681 }
4682 pw.println(" ");
4683 pw.println("Packages:");
4684 {
4685 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004686 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
4687 pw.print(Integer.toHexString(System.identityHashCode(ps)));
4688 pw.println("):");
4689 pw.print(" userId="); pw.print(ps.userId);
4690 pw.print(" gids="); pw.println(arrayToString(ps.gids));
4691 pw.print(" sharedUser="); pw.println(ps.sharedUser);
4692 pw.print(" pkg="); pw.println(ps.pkg);
4693 pw.print(" codePath="); pw.println(ps.codePathString);
4694 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004696 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004698 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
4699 pw.print(" signatures="); pw.println(ps.signatures);
4700 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
4701 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
4702 pw.print(" installStatus="); pw.print(ps.installStatus);
4703 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 if (ps.disabledComponents.size() > 0) {
4705 pw.println(" disabledComponents:");
4706 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004707 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 }
4709 }
4710 if (ps.enabledComponents.size() > 0) {
4711 pw.println(" enabledComponents:");
4712 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004713 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 }
4715 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004716 if (ps.grantedPermissions.size() > 0) {
4717 pw.println(" grantedPermissions:");
4718 for (String s : ps.grantedPermissions) {
4719 pw.print(" "); pw.println(s);
4720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004722 if (ps.loadedPermissions.size() > 0) {
4723 pw.println(" loadedPermissions:");
4724 for (String s : ps.loadedPermissions) {
4725 pw.print(" "); pw.println(s);
4726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 }
4728 }
4729 }
4730 pw.println(" ");
4731 pw.println("Shared Users:");
4732 {
4733 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004734 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
4735 pw.print(Integer.toHexString(System.identityHashCode(su)));
4736 pw.println("):");
4737 pw.print(" userId="); pw.print(su.userId);
4738 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 pw.println(" grantedPermissions:");
4740 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004741 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 }
4743 pw.println(" loadedPermissions:");
4744 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004745 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 }
4747 }
4748 }
4749 pw.println(" ");
4750 pw.println("Settings parse messages:");
4751 pw.println(mSettings.mReadMessages.toString());
4752 }
4753 }
4754
4755 static final class BasePermission {
4756 final static int TYPE_NORMAL = 0;
4757 final static int TYPE_BUILTIN = 1;
4758 final static int TYPE_DYNAMIC = 2;
4759
4760 final String name;
4761 final String sourcePackage;
4762 final int type;
4763 PackageParser.Permission perm;
4764 PermissionInfo pendingInfo;
4765 int uid;
4766 int[] gids;
4767
4768 BasePermission(String _name, String _sourcePackage, int _type) {
4769 name = _name;
4770 sourcePackage = _sourcePackage;
4771 type = _type;
4772 }
4773 }
4774
4775 static class PackageSignatures {
4776 private Signature[] mSignatures;
4777
4778 PackageSignatures(Signature[] sigs) {
4779 assignSignatures(sigs);
4780 }
4781
4782 PackageSignatures() {
4783 }
4784
4785 void writeXml(XmlSerializer serializer, String tagName,
4786 ArrayList<Signature> pastSignatures) throws IOException {
4787 if (mSignatures == null) {
4788 return;
4789 }
4790 serializer.startTag(null, tagName);
4791 serializer.attribute(null, "count",
4792 Integer.toString(mSignatures.length));
4793 for (int i=0; i<mSignatures.length; i++) {
4794 serializer.startTag(null, "cert");
4795 final Signature sig = mSignatures[i];
4796 final int sigHash = sig.hashCode();
4797 final int numPast = pastSignatures.size();
4798 int j;
4799 for (j=0; j<numPast; j++) {
4800 Signature pastSig = pastSignatures.get(j);
4801 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
4802 serializer.attribute(null, "index", Integer.toString(j));
4803 break;
4804 }
4805 }
4806 if (j >= numPast) {
4807 pastSignatures.add(sig);
4808 serializer.attribute(null, "index", Integer.toString(numPast));
4809 serializer.attribute(null, "key", sig.toCharsString());
4810 }
4811 serializer.endTag(null, "cert");
4812 }
4813 serializer.endTag(null, tagName);
4814 }
4815
4816 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
4817 throws IOException, XmlPullParserException {
4818 String countStr = parser.getAttributeValue(null, "count");
4819 if (countStr == null) {
4820 reportSettingsProblem(Log.WARN,
4821 "Error in package manager settings: <signatures> has"
4822 + " no count at " + parser.getPositionDescription());
4823 XmlUtils.skipCurrentTag(parser);
4824 }
4825 final int count = Integer.parseInt(countStr);
4826 mSignatures = new Signature[count];
4827 int pos = 0;
4828
4829 int outerDepth = parser.getDepth();
4830 int type;
4831 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4832 && (type != XmlPullParser.END_TAG
4833 || parser.getDepth() > outerDepth)) {
4834 if (type == XmlPullParser.END_TAG
4835 || type == XmlPullParser.TEXT) {
4836 continue;
4837 }
4838
4839 String tagName = parser.getName();
4840 if (tagName.equals("cert")) {
4841 if (pos < count) {
4842 String index = parser.getAttributeValue(null, "index");
4843 if (index != null) {
4844 try {
4845 int idx = Integer.parseInt(index);
4846 String key = parser.getAttributeValue(null, "key");
4847 if (key == null) {
4848 if (idx >= 0 && idx < pastSignatures.size()) {
4849 Signature sig = pastSignatures.get(idx);
4850 if (sig != null) {
4851 mSignatures[pos] = pastSignatures.get(idx);
4852 pos++;
4853 } else {
4854 reportSettingsProblem(Log.WARN,
4855 "Error in package manager settings: <cert> "
4856 + "index " + index + " is not defined at "
4857 + parser.getPositionDescription());
4858 }
4859 } else {
4860 reportSettingsProblem(Log.WARN,
4861 "Error in package manager settings: <cert> "
4862 + "index " + index + " is out of bounds at "
4863 + parser.getPositionDescription());
4864 }
4865 } else {
4866 while (pastSignatures.size() <= idx) {
4867 pastSignatures.add(null);
4868 }
4869 Signature sig = new Signature(key);
4870 pastSignatures.set(idx, sig);
4871 mSignatures[pos] = sig;
4872 pos++;
4873 }
4874 } catch (NumberFormatException e) {
4875 reportSettingsProblem(Log.WARN,
4876 "Error in package manager settings: <cert> "
4877 + "index " + index + " is not a number at "
4878 + parser.getPositionDescription());
4879 }
4880 } else {
4881 reportSettingsProblem(Log.WARN,
4882 "Error in package manager settings: <cert> has"
4883 + " no index at " + parser.getPositionDescription());
4884 }
4885 } else {
4886 reportSettingsProblem(Log.WARN,
4887 "Error in package manager settings: too "
4888 + "many <cert> tags, expected " + count
4889 + " at " + parser.getPositionDescription());
4890 }
4891 } else {
4892 reportSettingsProblem(Log.WARN,
4893 "Unknown element under <cert>: "
4894 + parser.getName());
4895 }
4896 XmlUtils.skipCurrentTag(parser);
4897 }
4898
4899 if (pos < count) {
4900 // Should never happen -- there is an error in the written
4901 // settings -- but if it does we don't want to generate
4902 // a bad array.
4903 Signature[] newSigs = new Signature[pos];
4904 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
4905 mSignatures = newSigs;
4906 }
4907 }
4908
4909 /**
4910 * If any of the given 'sigs' is contained in the existing signatures,
4911 * then completely replace the current signatures with the ones in
4912 * 'sigs'. This is used for updating an existing package to a newly
4913 * installed version.
4914 */
4915 boolean updateSignatures(Signature[] sigs, boolean update) {
4916 if (mSignatures == null) {
4917 if (update) {
4918 assignSignatures(sigs);
4919 }
4920 return true;
4921 }
4922 if (sigs == null) {
4923 return false;
4924 }
4925
4926 for (int i=0; i<sigs.length; i++) {
4927 Signature sig = sigs[i];
4928 for (int j=0; j<mSignatures.length; j++) {
4929 if (mSignatures[j].equals(sig)) {
4930 if (update) {
4931 assignSignatures(sigs);
4932 }
4933 return true;
4934 }
4935 }
4936 }
4937 return false;
4938 }
4939
4940 /**
4941 * If any of the given 'sigs' is contained in the existing signatures,
4942 * then add in any new signatures found in 'sigs'. This is used for
4943 * including a new package into an existing shared user id.
4944 */
4945 boolean mergeSignatures(Signature[] sigs, boolean update) {
4946 if (mSignatures == null) {
4947 if (update) {
4948 assignSignatures(sigs);
4949 }
4950 return true;
4951 }
4952 if (sigs == null) {
4953 return false;
4954 }
4955
4956 Signature[] added = null;
4957 int addedCount = 0;
4958 boolean haveMatch = false;
4959 for (int i=0; i<sigs.length; i++) {
4960 Signature sig = sigs[i];
4961 boolean found = false;
4962 for (int j=0; j<mSignatures.length; j++) {
4963 if (mSignatures[j].equals(sig)) {
4964 found = true;
4965 haveMatch = true;
4966 break;
4967 }
4968 }
4969
4970 if (!found) {
4971 if (added == null) {
4972 added = new Signature[sigs.length];
4973 }
4974 added[i] = sig;
4975 addedCount++;
4976 }
4977 }
4978
4979 if (!haveMatch) {
4980 // Nothing matched -- reject the new signatures.
4981 return false;
4982 }
4983 if (added == null) {
4984 // Completely matched -- nothing else to do.
4985 return true;
4986 }
4987
4988 // Add additional signatures in.
4989 if (update) {
4990 Signature[] total = new Signature[addedCount+mSignatures.length];
4991 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
4992 int j = mSignatures.length;
4993 for (int i=0; i<added.length; i++) {
4994 if (added[i] != null) {
4995 total[j] = added[i];
4996 j++;
4997 }
4998 }
4999 mSignatures = total;
5000 }
5001 return true;
5002 }
5003
5004 private void assignSignatures(Signature[] sigs) {
5005 if (sigs == null) {
5006 mSignatures = null;
5007 return;
5008 }
5009 mSignatures = new Signature[sigs.length];
5010 for (int i=0; i<sigs.length; i++) {
5011 mSignatures[i] = sigs[i];
5012 }
5013 }
5014
5015 @Override
5016 public String toString() {
5017 StringBuffer buf = new StringBuffer(128);
5018 buf.append("PackageSignatures{");
5019 buf.append(Integer.toHexString(System.identityHashCode(this)));
5020 buf.append(" [");
5021 if (mSignatures != null) {
5022 for (int i=0; i<mSignatures.length; i++) {
5023 if (i > 0) buf.append(", ");
5024 buf.append(Integer.toHexString(
5025 System.identityHashCode(mSignatures[i])));
5026 }
5027 }
5028 buf.append("]}");
5029 return buf.toString();
5030 }
5031 }
5032
5033 static class PreferredActivity extends IntentFilter {
5034 final int mMatch;
5035 final String[] mSetPackages;
5036 final String[] mSetClasses;
5037 final String[] mSetComponents;
5038 final ComponentName mActivity;
5039 final String mShortActivity;
5040 String mParseError;
5041
5042 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5043 ComponentName activity) {
5044 super(filter);
5045 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5046 mActivity = activity;
5047 mShortActivity = activity.flattenToShortString();
5048 mParseError = null;
5049 if (set != null) {
5050 final int N = set.length;
5051 String[] myPackages = new String[N];
5052 String[] myClasses = new String[N];
5053 String[] myComponents = new String[N];
5054 for (int i=0; i<N; i++) {
5055 ComponentName cn = set[i];
5056 if (cn == null) {
5057 mSetPackages = null;
5058 mSetClasses = null;
5059 mSetComponents = null;
5060 return;
5061 }
5062 myPackages[i] = cn.getPackageName().intern();
5063 myClasses[i] = cn.getClassName().intern();
5064 myComponents[i] = cn.flattenToShortString().intern();
5065 }
5066 mSetPackages = myPackages;
5067 mSetClasses = myClasses;
5068 mSetComponents = myComponents;
5069 } else {
5070 mSetPackages = null;
5071 mSetClasses = null;
5072 mSetComponents = null;
5073 }
5074 }
5075
5076 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5077 IOException {
5078 mShortActivity = parser.getAttributeValue(null, "name");
5079 mActivity = ComponentName.unflattenFromString(mShortActivity);
5080 if (mActivity == null) {
5081 mParseError = "Bad activity name " + mShortActivity;
5082 }
5083 String matchStr = parser.getAttributeValue(null, "match");
5084 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5085 String setCountStr = parser.getAttributeValue(null, "set");
5086 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5087
5088 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5089 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5090 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5091
5092 int setPos = 0;
5093
5094 int outerDepth = parser.getDepth();
5095 int type;
5096 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5097 && (type != XmlPullParser.END_TAG
5098 || parser.getDepth() > outerDepth)) {
5099 if (type == XmlPullParser.END_TAG
5100 || type == XmlPullParser.TEXT) {
5101 continue;
5102 }
5103
5104 String tagName = parser.getName();
5105 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5106 // + parser.getDepth() + " tag=" + tagName);
5107 if (tagName.equals("set")) {
5108 String name = parser.getAttributeValue(null, "name");
5109 if (name == null) {
5110 if (mParseError == null) {
5111 mParseError = "No name in set tag in preferred activity "
5112 + mShortActivity;
5113 }
5114 } else if (setPos >= setCount) {
5115 if (mParseError == null) {
5116 mParseError = "Too many set tags in preferred activity "
5117 + mShortActivity;
5118 }
5119 } else {
5120 ComponentName cn = ComponentName.unflattenFromString(name);
5121 if (cn == null) {
5122 if (mParseError == null) {
5123 mParseError = "Bad set name " + name + " in preferred activity "
5124 + mShortActivity;
5125 }
5126 } else {
5127 myPackages[setPos] = cn.getPackageName();
5128 myClasses[setPos] = cn.getClassName();
5129 myComponents[setPos] = name;
5130 setPos++;
5131 }
5132 }
5133 XmlUtils.skipCurrentTag(parser);
5134 } else if (tagName.equals("filter")) {
5135 //Log.i(TAG, "Starting to parse filter...");
5136 readFromXml(parser);
5137 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5138 // + parser.getDepth() + " tag=" + parser.getName());
5139 } else {
5140 reportSettingsProblem(Log.WARN,
5141 "Unknown element under <preferred-activities>: "
5142 + parser.getName());
5143 XmlUtils.skipCurrentTag(parser);
5144 }
5145 }
5146
5147 if (setPos != setCount) {
5148 if (mParseError == null) {
5149 mParseError = "Not enough set tags (expected " + setCount
5150 + " but found " + setPos + ") in " + mShortActivity;
5151 }
5152 }
5153
5154 mSetPackages = myPackages;
5155 mSetClasses = myClasses;
5156 mSetComponents = myComponents;
5157 }
5158
5159 public void writeToXml(XmlSerializer serializer) throws IOException {
5160 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5161 serializer.attribute(null, "name", mShortActivity);
5162 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5163 serializer.attribute(null, "set", Integer.toString(NS));
5164 for (int s=0; s<NS; s++) {
5165 serializer.startTag(null, "set");
5166 serializer.attribute(null, "name", mSetComponents[s]);
5167 serializer.endTag(null, "set");
5168 }
5169 serializer.startTag(null, "filter");
5170 super.writeToXml(serializer);
5171 serializer.endTag(null, "filter");
5172 }
5173
5174 boolean sameSet(List<ResolveInfo> query, int priority) {
5175 if (mSetPackages == null) return false;
5176 final int NQ = query.size();
5177 final int NS = mSetPackages.length;
5178 int numMatch = 0;
5179 for (int i=0; i<NQ; i++) {
5180 ResolveInfo ri = query.get(i);
5181 if (ri.priority != priority) continue;
5182 ActivityInfo ai = ri.activityInfo;
5183 boolean good = false;
5184 for (int j=0; j<NS; j++) {
5185 if (mSetPackages[j].equals(ai.packageName)
5186 && mSetClasses[j].equals(ai.name)) {
5187 numMatch++;
5188 good = true;
5189 break;
5190 }
5191 }
5192 if (!good) return false;
5193 }
5194 return numMatch == NS;
5195 }
5196 }
5197
5198 static class GrantedPermissions {
5199 final int pkgFlags;
5200
5201 HashSet<String> grantedPermissions = new HashSet<String>();
5202 int[] gids;
5203
5204 HashSet<String> loadedPermissions = new HashSet<String>();
5205
5206 GrantedPermissions(int pkgFlags) {
5207 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5208 }
5209 }
5210
5211 /**
5212 * Settings base class for pending and resolved classes.
5213 */
5214 static class PackageSettingBase extends GrantedPermissions {
5215 final String name;
5216 final File codePath;
5217 final String codePathString;
5218 final File resourcePath;
5219 final String resourcePathString;
5220 private long timeStamp;
5221 private String timeStampString = "0";
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005222 final int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223
5224 PackageSignatures signatures = new PackageSignatures();
5225
5226 boolean permissionsFixed;
5227
5228 /* Explicitly disabled components */
5229 HashSet<String> disabledComponents = new HashSet<String>(0);
5230 /* Explicitly enabled components */
5231 HashSet<String> enabledComponents = new HashSet<String>(0);
5232 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5233 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005234
5235 /* package name of the app that installed this package */
5236 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005237
5238 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005239 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 super(pkgFlags);
5241 this.name = name;
5242 this.codePath = codePath;
5243 this.codePathString = codePath.toString();
5244 this.resourcePath = resourcePath;
5245 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005246 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 }
5248
Jacek Surazski65e13172009-04-28 15:26:38 +02005249 public void setInstallerPackageName(String packageName) {
5250 installerPackageName = packageName;
5251 }
5252
5253 String getInstallerPackageName() {
5254 return installerPackageName;
5255 }
5256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 public void setInstallStatus(int newStatus) {
5258 installStatus = newStatus;
5259 }
5260
5261 public int getInstallStatus() {
5262 return installStatus;
5263 }
5264
5265 public void setTimeStamp(long newStamp) {
5266 if (newStamp != timeStamp) {
5267 timeStamp = newStamp;
5268 timeStampString = Long.toString(newStamp);
5269 }
5270 }
5271
5272 public void setTimeStamp(long newStamp, String newStampStr) {
5273 timeStamp = newStamp;
5274 timeStampString = newStampStr;
5275 }
5276
5277 public long getTimeStamp() {
5278 return timeStamp;
5279 }
5280
5281 public String getTimeStampStr() {
5282 return timeStampString;
5283 }
5284
5285 public void copyFrom(PackageSettingBase base) {
5286 grantedPermissions = base.grantedPermissions;
5287 gids = base.gids;
5288 loadedPermissions = base.loadedPermissions;
5289
5290 timeStamp = base.timeStamp;
5291 timeStampString = base.timeStampString;
5292 signatures = base.signatures;
5293 permissionsFixed = base.permissionsFixed;
5294 disabledComponents = base.disabledComponents;
5295 enabledComponents = base.enabledComponents;
5296 enabled = base.enabled;
5297 installStatus = base.installStatus;
5298 }
5299
5300 void enableComponentLP(String componentClassName) {
5301 disabledComponents.remove(componentClassName);
5302 enabledComponents.add(componentClassName);
5303 }
5304
5305 void disableComponentLP(String componentClassName) {
5306 enabledComponents.remove(componentClassName);
5307 disabledComponents.add(componentClassName);
5308 }
5309
5310 void restoreComponentLP(String componentClassName) {
5311 enabledComponents.remove(componentClassName);
5312 disabledComponents.remove(componentClassName);
5313 }
5314
5315 int currentEnabledStateLP(String componentName) {
5316 if (enabledComponents.contains(componentName)) {
5317 return COMPONENT_ENABLED_STATE_ENABLED;
5318 } else if (disabledComponents.contains(componentName)) {
5319 return COMPONENT_ENABLED_STATE_DISABLED;
5320 } else {
5321 return COMPONENT_ENABLED_STATE_DEFAULT;
5322 }
5323 }
5324 }
5325
5326 /**
5327 * Settings data for a particular package we know about.
5328 */
5329 static final class PackageSetting extends PackageSettingBase {
5330 int userId;
5331 PackageParser.Package pkg;
5332 SharedUserSetting sharedUser;
5333
5334 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005335 int pVersionCode, int pkgFlags) {
5336 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 }
5338
5339 @Override
5340 public String toString() {
5341 return "PackageSetting{"
5342 + Integer.toHexString(System.identityHashCode(this))
5343 + " " + name + "/" + userId + "}";
5344 }
5345 }
5346
5347 /**
5348 * Settings data for a particular shared user ID we know about.
5349 */
5350 static final class SharedUserSetting extends GrantedPermissions {
5351 final String name;
5352 int userId;
5353 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5354 final PackageSignatures signatures = new PackageSignatures();
5355
5356 SharedUserSetting(String _name, int _pkgFlags) {
5357 super(_pkgFlags);
5358 name = _name;
5359 }
5360
5361 @Override
5362 public String toString() {
5363 return "SharedUserSetting{"
5364 + Integer.toHexString(System.identityHashCode(this))
5365 + " " + name + "/" + userId + "}";
5366 }
5367 }
5368
5369 /**
5370 * Holds information about dynamic settings.
5371 */
5372 private static final class Settings {
5373 private final File mSettingsFilename;
5374 private final File mBackupSettingsFilename;
5375 private final HashMap<String, PackageSetting> mPackages =
5376 new HashMap<String, PackageSetting>();
5377 // The user's preferred packages/applications, in order of preference.
5378 // First is the most preferred.
5379 private final ArrayList<PackageSetting> mPreferredPackages =
5380 new ArrayList<PackageSetting>();
5381 // List of replaced system applications
5382 final HashMap<String, PackageSetting> mDisabledSysPackages =
5383 new HashMap<String, PackageSetting>();
5384
5385 // The user's preferred activities associated with particular intent
5386 // filters.
5387 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5388 new IntentResolver<PreferredActivity, PreferredActivity>() {
5389 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005390 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005392 out.print(prefix); out.print(
5393 Integer.toHexString(System.identityHashCode(filter)));
5394 out.print(' ');
5395 out.print(filter.mActivity.flattenToShortString());
5396 out.print(" match=0x");
5397 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005399 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005401 out.print(prefix); out.print(" ");
5402 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 }
5404 }
5405 }
5406 };
5407 private final HashMap<String, SharedUserSetting> mSharedUsers =
5408 new HashMap<String, SharedUserSetting>();
5409 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5410 private final SparseArray<Object> mOtherUserIds =
5411 new SparseArray<Object>();
5412
5413 // For reading/writing settings file.
5414 private final ArrayList<Signature> mPastSignatures =
5415 new ArrayList<Signature>();
5416
5417 // Mapping from permission names to info about them.
5418 final HashMap<String, BasePermission> mPermissions =
5419 new HashMap<String, BasePermission>();
5420
5421 // Mapping from permission tree names to info about them.
5422 final HashMap<String, BasePermission> mPermissionTrees =
5423 new HashMap<String, BasePermission>();
5424
5425 private final ArrayList<String> mPendingPreferredPackages
5426 = new ArrayList<String>();
5427
5428 private final StringBuilder mReadMessages = new StringBuilder();
5429
5430 private static final class PendingPackage extends PackageSettingBase {
5431 final int sharedId;
5432
5433 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005434 int sharedId, int pVersionCode, int pkgFlags) {
5435 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 this.sharedId = sharedId;
5437 }
5438 }
5439 private final ArrayList<PendingPackage> mPendingPackages
5440 = new ArrayList<PendingPackage>();
5441
5442 Settings() {
5443 File dataDir = Environment.getDataDirectory();
5444 File systemDir = new File(dataDir, "system");
5445 systemDir.mkdirs();
5446 FileUtils.setPermissions(systemDir.toString(),
5447 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5448 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5449 -1, -1);
5450 mSettingsFilename = new File(systemDir, "packages.xml");
5451 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5452 }
5453
5454 PackageSetting getPackageLP(PackageParser.Package pkg,
5455 SharedUserSetting sharedUser, File codePath, File resourcePath,
5456 int pkgFlags, boolean create, boolean add) {
5457 final String name = pkg.packageName;
5458 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005459 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460
5461 if (p != null) {
5462 p.pkg = pkg;
5463 }
5464 return p;
5465 }
5466
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005467 PackageSetting peekPackageLP(String name) {
5468 return mPackages.get(name);
5469 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 PackageSetting p = mPackages.get(name);
5471 if (p != null && p.codePath.getPath().equals(codePath)) {
5472 return p;
5473 }
5474 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005475 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005476 }
5477
5478 void setInstallStatus(String pkgName, int status) {
5479 PackageSetting p = mPackages.get(pkgName);
5480 if(p != null) {
5481 if(p.getInstallStatus() != status) {
5482 p.setInstallStatus(status);
5483 }
5484 }
5485 }
5486
Jacek Surazski65e13172009-04-28 15:26:38 +02005487 void setInstallerPackageName(String pkgName,
5488 String installerPkgName) {
5489 PackageSetting p = mPackages.get(pkgName);
5490 if(p != null) {
5491 p.setInstallerPackageName(installerPkgName);
5492 }
5493 }
5494
5495 String getInstallerPackageName(String pkgName) {
5496 PackageSetting p = mPackages.get(pkgName);
5497 return (p == null) ? null : p.getInstallerPackageName();
5498 }
5499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 int getInstallStatus(String pkgName) {
5501 PackageSetting p = mPackages.get(pkgName);
5502 if(p != null) {
5503 return p.getInstallStatus();
5504 }
5505 return -1;
5506 }
5507
5508 SharedUserSetting getSharedUserLP(String name,
5509 int pkgFlags, boolean create) {
5510 SharedUserSetting s = mSharedUsers.get(name);
5511 if (s == null) {
5512 if (!create) {
5513 return null;
5514 }
5515 s = new SharedUserSetting(name, pkgFlags);
5516 if (MULTIPLE_APPLICATION_UIDS) {
5517 s.userId = newUserIdLP(s);
5518 } else {
5519 s.userId = FIRST_APPLICATION_UID;
5520 }
5521 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
5522 // < 0 means we couldn't assign a userid; fall out and return
5523 // s, which is currently null
5524 if (s.userId >= 0) {
5525 mSharedUsers.put(name, s);
5526 }
5527 }
5528
5529 return s;
5530 }
5531
5532 int disableSystemPackageLP(String name) {
5533 PackageSetting p = mPackages.get(name);
5534 if(p == null) {
5535 Log.w(TAG, "Package:"+name+" is not an installed package");
5536 return -1;
5537 }
5538 PackageSetting dp = mDisabledSysPackages.get(name);
5539 // always make sure the system package code and resource paths dont change
5540 if(dp == null) {
5541 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5542 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5543 }
5544 mDisabledSysPackages.put(name, p);
5545 }
5546 return removePackageLP(name);
5547 }
5548
5549 PackageSetting enableSystemPackageLP(String name) {
5550 PackageSetting p = mDisabledSysPackages.get(name);
5551 if(p == null) {
5552 Log.w(TAG, "Package:"+name+" is not disabled");
5553 return null;
5554 }
5555 // Reset flag in ApplicationInfo object
5556 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5557 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5558 }
5559 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005560 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 mDisabledSysPackages.remove(name);
5562 return ret;
5563 }
5564
5565 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005566 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 PackageSetting p = mPackages.get(name);
5568 if (p != null) {
5569 if (p.userId == uid) {
5570 return p;
5571 }
5572 reportSettingsProblem(Log.ERROR,
5573 "Adding duplicate package, keeping first: " + name);
5574 return null;
5575 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005576 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 p.userId = uid;
5578 if (addUserIdLP(uid, p, name)) {
5579 mPackages.put(name, p);
5580 return p;
5581 }
5582 return null;
5583 }
5584
5585 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
5586 SharedUserSetting s = mSharedUsers.get(name);
5587 if (s != null) {
5588 if (s.userId == uid) {
5589 return s;
5590 }
5591 reportSettingsProblem(Log.ERROR,
5592 "Adding duplicate shared user, keeping first: " + name);
5593 return null;
5594 }
5595 s = new SharedUserSetting(name, pkgFlags);
5596 s.userId = uid;
5597 if (addUserIdLP(uid, s, name)) {
5598 mSharedUsers.put(name, s);
5599 return s;
5600 }
5601 return null;
5602 }
5603
5604 private PackageSetting getPackageLP(String name,
5605 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005606 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 PackageSetting p = mPackages.get(name);
5608 if (p != null) {
5609 if (!p.codePath.equals(codePath)) {
5610 // Check to see if its a disabled system app
5611 PackageSetting ps = mDisabledSysPackages.get(name);
5612 if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
5613 // Could be a replaced system package
5614 // Note that if the user replaced a system app, the user has to physically
5615 // delete the new one in order to revert to the system app. So even
5616 // if the user updated the system app via an update, the user still
5617 // has to delete the one installed in the data partition in order to pick up the
5618 // new system package.
5619 return p;
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07005620 } else if ((p.pkg != null) && (p.pkg.applicationInfo != null) &&
5621 ((p.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
5622 // Check for non-system apps
5623 reportSettingsProblem(Log.WARN,
5624 "Package " + name + " codePath changed from " + p.codePath
5625 + " to " + codePath + "; Retaining data and using new code");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 } else {
5627 reportSettingsProblem(Log.WARN,
5628 "Package " + name + " codePath changed from " + p.codePath
5629 + " to " + codePath + "; replacing with new");
5630 p = null;
5631 }
5632 } else if (p.sharedUser != sharedUser) {
5633 reportSettingsProblem(Log.WARN,
5634 "Package " + name + " shared user changed from "
5635 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
5636 + " to "
5637 + (sharedUser != null ? sharedUser.name : "<nothing>")
5638 + "; replacing with new");
5639 p = null;
5640 }
5641 }
5642 if (p == null) {
5643 // Create a new PackageSettings entry. this can end up here because
5644 // of code path mismatch or user id mismatch of an updated system partition
5645 if (!create) {
5646 return null;
5647 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005648 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 p.setTimeStamp(codePath.lastModified());
5650 if (sharedUser != null) {
5651 p.userId = sharedUser.userId;
5652 } else if (MULTIPLE_APPLICATION_UIDS) {
5653 p.userId = newUserIdLP(p);
5654 } else {
5655 p.userId = FIRST_APPLICATION_UID;
5656 }
5657 if (p.userId < 0) {
5658 reportSettingsProblem(Log.WARN,
5659 "Package " + name + " could not be assigned a valid uid");
5660 return null;
5661 }
5662 if (add) {
5663 // Finish adding new package by adding it and updating shared
5664 // user preferences
5665 insertPackageSettingLP(p, name, sharedUser);
5666 }
5667 }
5668 return p;
5669 }
5670
5671 // Utility method that adds a PackageSetting to mPackages and
5672 // completes updating the shared user attributes
5673 private void insertPackageSettingLP(PackageSetting p, String name,
5674 SharedUserSetting sharedUser) {
5675 mPackages.put(name, p);
5676 if (sharedUser != null) {
5677 if (p.sharedUser != null && p.sharedUser != sharedUser) {
5678 reportSettingsProblem(Log.ERROR,
5679 "Package " + p.name + " was user "
5680 + p.sharedUser + " but is now " + sharedUser
5681 + "; I am not changing its files so it will probably fail!");
5682 p.sharedUser.packages.remove(p);
5683 } else if (p.userId != sharedUser.userId) {
5684 reportSettingsProblem(Log.ERROR,
5685 "Package " + p.name + " was user id " + p.userId
5686 + " but is now user " + sharedUser
5687 + " with id " + sharedUser.userId
5688 + "; I am not changing its files so it will probably fail!");
5689 }
5690
5691 sharedUser.packages.add(p);
5692 p.sharedUser = sharedUser;
5693 p.userId = sharedUser.userId;
5694 }
5695 }
5696
5697 private void updateSharedUserPerms (PackageSetting deletedPs) {
5698 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
5699 Log.i(TAG, "Trying to update info for null package. Just ignoring");
5700 return;
5701 }
5702 // No sharedUserId
5703 if (deletedPs.sharedUser == null) {
5704 return;
5705 }
5706 SharedUserSetting sus = deletedPs.sharedUser;
5707 // Update permissions
5708 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
5709 boolean used = false;
5710 if (!sus.grantedPermissions.contains (eachPerm)) {
5711 continue;
5712 }
5713 for (PackageSetting pkg:sus.packages) {
5714 if (pkg.grantedPermissions.contains (eachPerm)) {
5715 used = true;
5716 break;
5717 }
5718 }
5719 if (!used) {
5720 // can safely delete this permission from list
5721 sus.grantedPermissions.remove(eachPerm);
5722 sus.loadedPermissions.remove(eachPerm);
5723 }
5724 }
5725 // Update gids
5726 int newGids[] = null;
5727 for (PackageSetting pkg:sus.packages) {
5728 newGids = appendInts(newGids, pkg.gids);
5729 }
5730 sus.gids = newGids;
5731 }
5732
5733 private int removePackageLP(String name) {
5734 PackageSetting p = mPackages.get(name);
5735 if (p != null) {
5736 mPackages.remove(name);
5737 if (p.sharedUser != null) {
5738 p.sharedUser.packages.remove(p);
5739 if (p.sharedUser.packages.size() == 0) {
5740 mSharedUsers.remove(p.sharedUser.name);
5741 removeUserIdLP(p.sharedUser.userId);
5742 return p.sharedUser.userId;
5743 }
5744 } else {
5745 removeUserIdLP(p.userId);
5746 return p.userId;
5747 }
5748 }
5749 return -1;
5750 }
5751
5752 private boolean addUserIdLP(int uid, Object obj, Object name) {
5753 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
5754 return false;
5755 }
5756
5757 if (uid >= FIRST_APPLICATION_UID) {
5758 int N = mUserIds.size();
5759 final int index = uid - FIRST_APPLICATION_UID;
5760 while (index >= N) {
5761 mUserIds.add(null);
5762 N++;
5763 }
5764 if (mUserIds.get(index) != null) {
5765 reportSettingsProblem(Log.ERROR,
5766 "Adding duplicate shared id: " + uid
5767 + " name=" + name);
5768 return false;
5769 }
5770 mUserIds.set(index, obj);
5771 } else {
5772 if (mOtherUserIds.get(uid) != null) {
5773 reportSettingsProblem(Log.ERROR,
5774 "Adding duplicate shared id: " + uid
5775 + " name=" + name);
5776 return false;
5777 }
5778 mOtherUserIds.put(uid, obj);
5779 }
5780 return true;
5781 }
5782
5783 public Object getUserIdLP(int uid) {
5784 if (uid >= FIRST_APPLICATION_UID) {
5785 int N = mUserIds.size();
5786 final int index = uid - FIRST_APPLICATION_UID;
5787 return index < N ? mUserIds.get(index) : null;
5788 } else {
5789 return mOtherUserIds.get(uid);
5790 }
5791 }
5792
5793 private void removeUserIdLP(int uid) {
5794 if (uid >= FIRST_APPLICATION_UID) {
5795 int N = mUserIds.size();
5796 final int index = uid - FIRST_APPLICATION_UID;
5797 if (index < N) mUserIds.set(index, null);
5798 } else {
5799 mOtherUserIds.remove(uid);
5800 }
5801 }
5802
5803 void writeLP() {
5804 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
5805
5806 // Keep the old settings around until we know the new ones have
5807 // been successfully written.
5808 if (mSettingsFilename.exists()) {
5809 if (mBackupSettingsFilename.exists()) {
5810 mBackupSettingsFilename.delete();
5811 }
5812 mSettingsFilename.renameTo(mBackupSettingsFilename);
5813 }
5814
5815 mPastSignatures.clear();
5816
5817 try {
5818 FileOutputStream str = new FileOutputStream(mSettingsFilename);
5819
5820 //XmlSerializer serializer = XmlUtils.serializerInstance();
5821 XmlSerializer serializer = new FastXmlSerializer();
5822 serializer.setOutput(str, "utf-8");
5823 serializer.startDocument(null, true);
5824 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
5825
5826 serializer.startTag(null, "packages");
5827
5828 serializer.startTag(null, "permission-trees");
5829 for (BasePermission bp : mPermissionTrees.values()) {
5830 writePermission(serializer, bp);
5831 }
5832 serializer.endTag(null, "permission-trees");
5833
5834 serializer.startTag(null, "permissions");
5835 for (BasePermission bp : mPermissions.values()) {
5836 writePermission(serializer, bp);
5837 }
5838 serializer.endTag(null, "permissions");
5839
5840 for (PackageSetting pkg : mPackages.values()) {
5841 writePackage(serializer, pkg);
5842 }
5843
5844 for (PackageSetting pkg : mDisabledSysPackages.values()) {
5845 writeDisabledSysPackage(serializer, pkg);
5846 }
5847
5848 serializer.startTag(null, "preferred-packages");
5849 int N = mPreferredPackages.size();
5850 for (int i=0; i<N; i++) {
5851 PackageSetting pkg = mPreferredPackages.get(i);
5852 serializer.startTag(null, "item");
5853 serializer.attribute(null, "name", pkg.name);
5854 serializer.endTag(null, "item");
5855 }
5856 serializer.endTag(null, "preferred-packages");
5857
5858 serializer.startTag(null, "preferred-activities");
5859 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
5860 serializer.startTag(null, "item");
5861 pa.writeToXml(serializer);
5862 serializer.endTag(null, "item");
5863 }
5864 serializer.endTag(null, "preferred-activities");
5865
5866 for (SharedUserSetting usr : mSharedUsers.values()) {
5867 serializer.startTag(null, "shared-user");
5868 serializer.attribute(null, "name", usr.name);
5869 serializer.attribute(null, "userId",
5870 Integer.toString(usr.userId));
5871 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
5872 serializer.startTag(null, "perms");
5873 for (String name : usr.grantedPermissions) {
5874 serializer.startTag(null, "item");
5875 serializer.attribute(null, "name", name);
5876 serializer.endTag(null, "item");
5877 }
5878 serializer.endTag(null, "perms");
5879 serializer.endTag(null, "shared-user");
5880 }
5881
5882 serializer.endTag(null, "packages");
5883
5884 serializer.endDocument();
5885
5886 str.flush();
5887 str.close();
5888
5889 // New settings successfully written, old ones are no longer
5890 // needed.
5891 mBackupSettingsFilename.delete();
5892 FileUtils.setPermissions(mSettingsFilename.toString(),
5893 FileUtils.S_IRUSR|FileUtils.S_IWUSR
5894 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
5895 |FileUtils.S_IROTH,
5896 -1, -1);
5897
5898 } catch(XmlPullParserException e) {
5899 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5900
5901 } catch(java.io.IOException e) {
5902 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5903
5904 }
5905
5906 //Debug.stopMethodTracing();
5907 }
5908
5909 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
5910 throws java.io.IOException {
5911 serializer.startTag(null, "updated-package");
5912 serializer.attribute(null, "name", pkg.name);
5913 serializer.attribute(null, "codePath", pkg.codePathString);
5914 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005915 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5917 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5918 }
5919 if (pkg.sharedUser == null) {
5920 serializer.attribute(null, "userId",
5921 Integer.toString(pkg.userId));
5922 } else {
5923 serializer.attribute(null, "sharedUserId",
5924 Integer.toString(pkg.userId));
5925 }
5926 serializer.startTag(null, "perms");
5927 if (pkg.sharedUser == null) {
5928 // If this is a shared user, the permissions will
5929 // be written there. We still need to write an
5930 // empty permissions list so permissionsFixed will
5931 // be set.
5932 for (final String name : pkg.grantedPermissions) {
5933 BasePermission bp = mPermissions.get(name);
5934 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
5935 // We only need to write signature or system permissions but this wont
5936 // match the semantics of grantedPermissions. So write all permissions.
5937 serializer.startTag(null, "item");
5938 serializer.attribute(null, "name", name);
5939 serializer.endTag(null, "item");
5940 }
5941 }
5942 }
5943 serializer.endTag(null, "perms");
5944 serializer.endTag(null, "updated-package");
5945 }
5946
5947 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
5948 throws java.io.IOException {
5949 serializer.startTag(null, "package");
5950 serializer.attribute(null, "name", pkg.name);
5951 serializer.attribute(null, "codePath", pkg.codePathString);
5952 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5953 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5954 }
5955 serializer.attribute(null, "system",
5956 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
5957 ? "true" : "false");
5958 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005959 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 if (pkg.sharedUser == null) {
5961 serializer.attribute(null, "userId",
5962 Integer.toString(pkg.userId));
5963 } else {
5964 serializer.attribute(null, "sharedUserId",
5965 Integer.toString(pkg.userId));
5966 }
5967 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
5968 serializer.attribute(null, "enabled",
5969 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
5970 ? "true" : "false");
5971 }
5972 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
5973 serializer.attribute(null, "installStatus", "false");
5974 }
Jacek Surazski65e13172009-04-28 15:26:38 +02005975 if (pkg.installerPackageName != null) {
5976 serializer.attribute(null, "installer", pkg.installerPackageName);
5977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
5979 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5980 serializer.startTag(null, "perms");
5981 if (pkg.sharedUser == null) {
5982 // If this is a shared user, the permissions will
5983 // be written there. We still need to write an
5984 // empty permissions list so permissionsFixed will
5985 // be set.
5986 for (final String name : pkg.grantedPermissions) {
5987 serializer.startTag(null, "item");
5988 serializer.attribute(null, "name", name);
5989 serializer.endTag(null, "item");
5990 }
5991 }
5992 serializer.endTag(null, "perms");
5993 }
5994 if (pkg.disabledComponents.size() > 0) {
5995 serializer.startTag(null, "disabled-components");
5996 for (final String name : pkg.disabledComponents) {
5997 serializer.startTag(null, "item");
5998 serializer.attribute(null, "name", name);
5999 serializer.endTag(null, "item");
6000 }
6001 serializer.endTag(null, "disabled-components");
6002 }
6003 if (pkg.enabledComponents.size() > 0) {
6004 serializer.startTag(null, "enabled-components");
6005 for (final String name : pkg.enabledComponents) {
6006 serializer.startTag(null, "item");
6007 serializer.attribute(null, "name", name);
6008 serializer.endTag(null, "item");
6009 }
6010 serializer.endTag(null, "enabled-components");
6011 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 serializer.endTag(null, "package");
6014 }
6015
6016 void writePermission(XmlSerializer serializer, BasePermission bp)
6017 throws XmlPullParserException, java.io.IOException {
6018 if (bp.type != BasePermission.TYPE_BUILTIN
6019 && bp.sourcePackage != null) {
6020 serializer.startTag(null, "item");
6021 serializer.attribute(null, "name", bp.name);
6022 serializer.attribute(null, "package", bp.sourcePackage);
6023 if (DEBUG_SETTINGS) Log.v(TAG,
6024 "Writing perm: name=" + bp.name + " type=" + bp.type);
6025 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6026 PermissionInfo pi = bp.perm != null ? bp.perm.info
6027 : bp.pendingInfo;
6028 if (pi != null) {
6029 serializer.attribute(null, "type", "dynamic");
6030 if (pi.icon != 0) {
6031 serializer.attribute(null, "icon",
6032 Integer.toString(pi.icon));
6033 }
6034 if (pi.nonLocalizedLabel != null) {
6035 serializer.attribute(null, "label",
6036 pi.nonLocalizedLabel.toString());
6037 }
6038 if (pi.protectionLevel !=
6039 PermissionInfo.PROTECTION_NORMAL) {
6040 serializer.attribute(null, "protection",
6041 Integer.toString(pi.protectionLevel));
6042 }
6043 }
6044 }
6045 serializer.endTag(null, "item");
6046 }
6047 }
6048
6049 String getReadMessagesLP() {
6050 return mReadMessages.toString();
6051 }
6052
6053 ArrayList<String> getListOfIncompleteInstallPackages() {
6054 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6055 Iterator<String> its = kList.iterator();
6056 ArrayList<String> ret = new ArrayList<String>();
6057 while(its.hasNext()) {
6058 String key = its.next();
6059 PackageSetting ps = mPackages.get(key);
6060 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6061 ret.add(key);
6062 }
6063 }
6064 return ret;
6065 }
6066
6067 boolean readLP() {
6068 FileInputStream str = null;
6069 if (mBackupSettingsFilename.exists()) {
6070 try {
6071 str = new FileInputStream(mBackupSettingsFilename);
6072 mReadMessages.append("Reading from backup settings file\n");
6073 Log.i(TAG, "Reading from backup settings file!");
6074 } catch (java.io.IOException e) {
6075 // We'll try for the normal settings file.
6076 }
6077 }
6078
6079 mPastSignatures.clear();
6080
6081 try {
6082 if (str == null) {
6083 if (!mSettingsFilename.exists()) {
6084 mReadMessages.append("No settings file found\n");
6085 Log.i(TAG, "No current settings file!");
6086 return false;
6087 }
6088 str = new FileInputStream(mSettingsFilename);
6089 }
6090 XmlPullParser parser = Xml.newPullParser();
6091 parser.setInput(str, null);
6092
6093 int type;
6094 while ((type=parser.next()) != XmlPullParser.START_TAG
6095 && type != XmlPullParser.END_DOCUMENT) {
6096 ;
6097 }
6098
6099 if (type != XmlPullParser.START_TAG) {
6100 mReadMessages.append("No start tag found in settings file\n");
6101 Log.e(TAG, "No start tag found in package manager settings");
6102 return false;
6103 }
6104
6105 int outerDepth = parser.getDepth();
6106 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6107 && (type != XmlPullParser.END_TAG
6108 || parser.getDepth() > outerDepth)) {
6109 if (type == XmlPullParser.END_TAG
6110 || type == XmlPullParser.TEXT) {
6111 continue;
6112 }
6113
6114 String tagName = parser.getName();
6115 if (tagName.equals("package")) {
6116 readPackageLP(parser);
6117 } else if (tagName.equals("permissions")) {
6118 readPermissionsLP(mPermissions, parser);
6119 } else if (tagName.equals("permission-trees")) {
6120 readPermissionsLP(mPermissionTrees, parser);
6121 } else if (tagName.equals("shared-user")) {
6122 readSharedUserLP(parser);
6123 } else if (tagName.equals("preferred-packages")) {
6124 readPreferredPackagesLP(parser);
6125 } else if (tagName.equals("preferred-activities")) {
6126 readPreferredActivitiesLP(parser);
6127 } else if(tagName.equals("updated-package")) {
6128 readDisabledSysPackageLP(parser);
6129 } else {
6130 Log.w(TAG, "Unknown element under <packages>: "
6131 + parser.getName());
6132 XmlUtils.skipCurrentTag(parser);
6133 }
6134 }
6135
6136 str.close();
6137
6138 } catch(XmlPullParserException e) {
6139 mReadMessages.append("Error reading: " + e.toString());
6140 Log.e(TAG, "Error reading package manager settings", e);
6141
6142 } catch(java.io.IOException e) {
6143 mReadMessages.append("Error reading: " + e.toString());
6144 Log.e(TAG, "Error reading package manager settings", e);
6145
6146 }
6147
6148 int N = mPendingPackages.size();
6149 for (int i=0; i<N; i++) {
6150 final PendingPackage pp = mPendingPackages.get(i);
6151 Object idObj = getUserIdLP(pp.sharedId);
6152 if (idObj != null && idObj instanceof SharedUserSetting) {
6153 PackageSetting p = getPackageLP(pp.name,
6154 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006155 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 if (p == null) {
6157 Log.w(TAG, "Unable to create application package for "
6158 + pp.name);
6159 continue;
6160 }
6161 p.copyFrom(pp);
6162 } else if (idObj != null) {
6163 String msg = "Bad package setting: package " + pp.name
6164 + " has shared uid " + pp.sharedId
6165 + " that is not a shared uid\n";
6166 mReadMessages.append(msg);
6167 Log.e(TAG, msg);
6168 } else {
6169 String msg = "Bad package setting: package " + pp.name
6170 + " has shared uid " + pp.sharedId
6171 + " that is not defined\n";
6172 mReadMessages.append(msg);
6173 Log.e(TAG, msg);
6174 }
6175 }
6176 mPendingPackages.clear();
6177
6178 N = mPendingPreferredPackages.size();
6179 mPreferredPackages.clear();
6180 for (int i=0; i<N; i++) {
6181 final String name = mPendingPreferredPackages.get(i);
6182 final PackageSetting p = mPackages.get(name);
6183 if (p != null) {
6184 mPreferredPackages.add(p);
6185 } else {
6186 Log.w(TAG, "Unknown preferred package: " + name);
6187 }
6188 }
6189 mPendingPreferredPackages.clear();
6190
6191 mReadMessages.append("Read completed successfully: "
6192 + mPackages.size() + " packages, "
6193 + mSharedUsers.size() + " shared uids\n");
6194
6195 return true;
6196 }
6197
6198 private int readInt(XmlPullParser parser, String ns, String name,
6199 int defValue) {
6200 String v = parser.getAttributeValue(ns, name);
6201 try {
6202 if (v == null) {
6203 return defValue;
6204 }
6205 return Integer.parseInt(v);
6206 } catch (NumberFormatException e) {
6207 reportSettingsProblem(Log.WARN,
6208 "Error in package manager settings: attribute " +
6209 name + " has bad integer value " + v + " at "
6210 + parser.getPositionDescription());
6211 }
6212 return defValue;
6213 }
6214
6215 private void readPermissionsLP(HashMap<String, BasePermission> out,
6216 XmlPullParser parser)
6217 throws IOException, XmlPullParserException {
6218 int outerDepth = parser.getDepth();
6219 int type;
6220 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6221 && (type != XmlPullParser.END_TAG
6222 || parser.getDepth() > outerDepth)) {
6223 if (type == XmlPullParser.END_TAG
6224 || type == XmlPullParser.TEXT) {
6225 continue;
6226 }
6227
6228 String tagName = parser.getName();
6229 if (tagName.equals("item")) {
6230 String name = parser.getAttributeValue(null, "name");
6231 String sourcePackage = parser.getAttributeValue(null, "package");
6232 String ptype = parser.getAttributeValue(null, "type");
6233 if (name != null && sourcePackage != null) {
6234 boolean dynamic = "dynamic".equals(ptype);
6235 BasePermission bp = new BasePermission(name, sourcePackage,
6236 dynamic
6237 ? BasePermission.TYPE_DYNAMIC
6238 : BasePermission.TYPE_NORMAL);
6239 if (dynamic) {
6240 PermissionInfo pi = new PermissionInfo();
6241 pi.packageName = sourcePackage.intern();
6242 pi.name = name.intern();
6243 pi.icon = readInt(parser, null, "icon", 0);
6244 pi.nonLocalizedLabel = parser.getAttributeValue(
6245 null, "label");
6246 pi.protectionLevel = readInt(parser, null, "protection",
6247 PermissionInfo.PROTECTION_NORMAL);
6248 bp.pendingInfo = pi;
6249 }
6250 out.put(bp.name, bp);
6251 } else {
6252 reportSettingsProblem(Log.WARN,
6253 "Error in package manager settings: permissions has"
6254 + " no name at " + parser.getPositionDescription());
6255 }
6256 } else {
6257 reportSettingsProblem(Log.WARN,
6258 "Unknown element reading permissions: "
6259 + parser.getName() + " at "
6260 + parser.getPositionDescription());
6261 }
6262 XmlUtils.skipCurrentTag(parser);
6263 }
6264 }
6265
6266 private void readDisabledSysPackageLP(XmlPullParser parser)
6267 throws XmlPullParserException, IOException {
6268 String name = parser.getAttributeValue(null, "name");
6269 String codePathStr = parser.getAttributeValue(null, "codePath");
6270 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6271 if(resourcePathStr == null) {
6272 resourcePathStr = codePathStr;
6273 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006274 String version = parser.getAttributeValue(null, "version");
6275 int versionCode = 0;
6276 if (version != null) {
6277 try {
6278 versionCode = Integer.parseInt(version);
6279 } catch (NumberFormatException e) {
6280 }
6281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282
6283 int pkgFlags = 0;
6284 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6285 PackageSetting ps = new PackageSetting(name,
6286 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006287 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 String timeStampStr = parser.getAttributeValue(null, "ts");
6289 if (timeStampStr != null) {
6290 try {
6291 long timeStamp = Long.parseLong(timeStampStr);
6292 ps.setTimeStamp(timeStamp, timeStampStr);
6293 } catch (NumberFormatException e) {
6294 }
6295 }
6296 String idStr = parser.getAttributeValue(null, "userId");
6297 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6298 if(ps.userId <= 0) {
6299 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6300 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6301 }
6302 int outerDepth = parser.getDepth();
6303 int type;
6304 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6305 && (type != XmlPullParser.END_TAG
6306 || parser.getDepth() > outerDepth)) {
6307 if (type == XmlPullParser.END_TAG
6308 || type == XmlPullParser.TEXT) {
6309 continue;
6310 }
6311
6312 String tagName = parser.getName();
6313 if (tagName.equals("perms")) {
6314 readGrantedPermissionsLP(parser,
6315 ps.grantedPermissions);
6316 } else {
6317 reportSettingsProblem(Log.WARN,
6318 "Unknown element under <updated-package>: "
6319 + parser.getName());
6320 XmlUtils.skipCurrentTag(parser);
6321 }
6322 }
6323 mDisabledSysPackages.put(name, ps);
6324 }
6325
6326 private void readPackageLP(XmlPullParser parser)
6327 throws XmlPullParserException, IOException {
6328 String name = null;
6329 String idStr = null;
6330 String sharedIdStr = null;
6331 String codePathStr = null;
6332 String resourcePathStr = null;
6333 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02006334 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 int pkgFlags = 0;
6336 String timeStampStr;
6337 long timeStamp = 0;
6338 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006339 String version = null;
6340 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 try {
6342 name = parser.getAttributeValue(null, "name");
6343 idStr = parser.getAttributeValue(null, "userId");
6344 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6345 codePathStr = parser.getAttributeValue(null, "codePath");
6346 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006347 version = parser.getAttributeValue(null, "version");
6348 if (version != null) {
6349 try {
6350 versionCode = Integer.parseInt(version);
6351 } catch (NumberFormatException e) {
6352 }
6353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006354 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02006355 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 if (systemStr != null) {
6357 if ("true".equals(systemStr)) {
6358 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6359 }
6360 } else {
6361 // Old settings that don't specify system... just treat
6362 // them as system, good enough.
6363 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6364 }
6365 timeStampStr = parser.getAttributeValue(null, "ts");
6366 if (timeStampStr != null) {
6367 try {
6368 timeStamp = Long.parseLong(timeStampStr);
6369 } catch (NumberFormatException e) {
6370 }
6371 }
6372 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6373 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6374 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6375 if (resourcePathStr == null) {
6376 resourcePathStr = codePathStr;
6377 }
6378 if (name == null) {
6379 reportSettingsProblem(Log.WARN,
6380 "Error in package manager settings: <package> has no name at "
6381 + parser.getPositionDescription());
6382 } else if (codePathStr == null) {
6383 reportSettingsProblem(Log.WARN,
6384 "Error in package manager settings: <package> has no codePath at "
6385 + parser.getPositionDescription());
6386 } else if (userId > 0) {
6387 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006388 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006389 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6390 + ": userId=" + userId + " pkg=" + packageSetting);
6391 if (packageSetting == null) {
6392 reportSettingsProblem(Log.ERROR,
6393 "Failure adding uid " + userId
6394 + " while parsing settings at "
6395 + parser.getPositionDescription());
6396 } else {
6397 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6398 }
6399 } else if (sharedIdStr != null) {
6400 userId = sharedIdStr != null
6401 ? Integer.parseInt(sharedIdStr) : 0;
6402 if (userId > 0) {
6403 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006404 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6406 mPendingPackages.add((PendingPackage) packageSetting);
6407 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6408 + ": sharedUserId=" + userId + " pkg="
6409 + packageSetting);
6410 } else {
6411 reportSettingsProblem(Log.WARN,
6412 "Error in package manager settings: package "
6413 + name + " has bad sharedId " + sharedIdStr
6414 + " at " + parser.getPositionDescription());
6415 }
6416 } else {
6417 reportSettingsProblem(Log.WARN,
6418 "Error in package manager settings: package "
6419 + name + " has bad userId " + idStr + " at "
6420 + parser.getPositionDescription());
6421 }
6422 } catch (NumberFormatException e) {
6423 reportSettingsProblem(Log.WARN,
6424 "Error in package manager settings: package "
6425 + name + " has bad userId " + idStr + " at "
6426 + parser.getPositionDescription());
6427 }
6428 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02006429 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 final String enabledStr = parser.getAttributeValue(null, "enabled");
6431 if (enabledStr != null) {
6432 if (enabledStr.equalsIgnoreCase("true")) {
6433 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
6434 } else if (enabledStr.equalsIgnoreCase("false")) {
6435 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
6436 } else if (enabledStr.equalsIgnoreCase("default")) {
6437 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6438 } else {
6439 reportSettingsProblem(Log.WARN,
6440 "Error in package manager settings: package "
6441 + name + " has bad enabled value: " + idStr
6442 + " at " + parser.getPositionDescription());
6443 }
6444 } else {
6445 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6446 }
6447 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
6448 if (installStatusStr != null) {
6449 if (installStatusStr.equalsIgnoreCase("false")) {
6450 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
6451 } else {
6452 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
6453 }
6454 }
6455
6456 int outerDepth = parser.getDepth();
6457 int type;
6458 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6459 && (type != XmlPullParser.END_TAG
6460 || parser.getDepth() > outerDepth)) {
6461 if (type == XmlPullParser.END_TAG
6462 || type == XmlPullParser.TEXT) {
6463 continue;
6464 }
6465
6466 String tagName = parser.getName();
6467 if (tagName.equals("disabled-components")) {
6468 readDisabledComponentsLP(packageSetting, parser);
6469 } else if (tagName.equals("enabled-components")) {
6470 readEnabledComponentsLP(packageSetting, parser);
6471 } else if (tagName.equals("sigs")) {
6472 packageSetting.signatures.readXml(parser, mPastSignatures);
6473 } else if (tagName.equals("perms")) {
6474 readGrantedPermissionsLP(parser,
6475 packageSetting.loadedPermissions);
6476 packageSetting.permissionsFixed = true;
6477 } else {
6478 reportSettingsProblem(Log.WARN,
6479 "Unknown element under <package>: "
6480 + parser.getName());
6481 XmlUtils.skipCurrentTag(parser);
6482 }
6483 }
6484 } else {
6485 XmlUtils.skipCurrentTag(parser);
6486 }
6487 }
6488
6489 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
6490 XmlPullParser parser)
6491 throws IOException, XmlPullParserException {
6492 int outerDepth = parser.getDepth();
6493 int type;
6494 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6495 && (type != XmlPullParser.END_TAG
6496 || parser.getDepth() > outerDepth)) {
6497 if (type == XmlPullParser.END_TAG
6498 || type == XmlPullParser.TEXT) {
6499 continue;
6500 }
6501
6502 String tagName = parser.getName();
6503 if (tagName.equals("item")) {
6504 String name = parser.getAttributeValue(null, "name");
6505 if (name != null) {
6506 packageSetting.disabledComponents.add(name.intern());
6507 } else {
6508 reportSettingsProblem(Log.WARN,
6509 "Error in package manager settings: <disabled-components> has"
6510 + " no name at " + parser.getPositionDescription());
6511 }
6512 } else {
6513 reportSettingsProblem(Log.WARN,
6514 "Unknown element under <disabled-components>: "
6515 + parser.getName());
6516 }
6517 XmlUtils.skipCurrentTag(parser);
6518 }
6519 }
6520
6521 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
6522 XmlPullParser parser)
6523 throws IOException, XmlPullParserException {
6524 int outerDepth = parser.getDepth();
6525 int type;
6526 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6527 && (type != XmlPullParser.END_TAG
6528 || parser.getDepth() > outerDepth)) {
6529 if (type == XmlPullParser.END_TAG
6530 || type == XmlPullParser.TEXT) {
6531 continue;
6532 }
6533
6534 String tagName = parser.getName();
6535 if (tagName.equals("item")) {
6536 String name = parser.getAttributeValue(null, "name");
6537 if (name != null) {
6538 packageSetting.enabledComponents.add(name.intern());
6539 } else {
6540 reportSettingsProblem(Log.WARN,
6541 "Error in package manager settings: <enabled-components> has"
6542 + " no name at " + parser.getPositionDescription());
6543 }
6544 } else {
6545 reportSettingsProblem(Log.WARN,
6546 "Unknown element under <enabled-components>: "
6547 + parser.getName());
6548 }
6549 XmlUtils.skipCurrentTag(parser);
6550 }
6551 }
6552
6553 private void readSharedUserLP(XmlPullParser parser)
6554 throws XmlPullParserException, IOException {
6555 String name = null;
6556 String idStr = null;
6557 int pkgFlags = 0;
6558 SharedUserSetting su = null;
6559 try {
6560 name = parser.getAttributeValue(null, "name");
6561 idStr = parser.getAttributeValue(null, "userId");
6562 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6563 if ("true".equals(parser.getAttributeValue(null, "system"))) {
6564 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6565 }
6566 if (name == null) {
6567 reportSettingsProblem(Log.WARN,
6568 "Error in package manager settings: <shared-user> has no name at "
6569 + parser.getPositionDescription());
6570 } else if (userId == 0) {
6571 reportSettingsProblem(Log.WARN,
6572 "Error in package manager settings: shared-user "
6573 + name + " has bad userId " + idStr + " at "
6574 + parser.getPositionDescription());
6575 } else {
6576 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
6577 reportSettingsProblem(Log.ERROR,
6578 "Occurred while parsing settings at "
6579 + parser.getPositionDescription());
6580 }
6581 }
6582 } catch (NumberFormatException e) {
6583 reportSettingsProblem(Log.WARN,
6584 "Error in package manager settings: package "
6585 + name + " has bad userId " + idStr + " at "
6586 + parser.getPositionDescription());
6587 };
6588
6589 if (su != null) {
6590 int outerDepth = parser.getDepth();
6591 int type;
6592 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6593 && (type != XmlPullParser.END_TAG
6594 || parser.getDepth() > outerDepth)) {
6595 if (type == XmlPullParser.END_TAG
6596 || type == XmlPullParser.TEXT) {
6597 continue;
6598 }
6599
6600 String tagName = parser.getName();
6601 if (tagName.equals("sigs")) {
6602 su.signatures.readXml(parser, mPastSignatures);
6603 } else if (tagName.equals("perms")) {
6604 readGrantedPermissionsLP(parser, su.loadedPermissions);
6605 } else {
6606 reportSettingsProblem(Log.WARN,
6607 "Unknown element under <shared-user>: "
6608 + parser.getName());
6609 XmlUtils.skipCurrentTag(parser);
6610 }
6611 }
6612
6613 } else {
6614 XmlUtils.skipCurrentTag(parser);
6615 }
6616 }
6617
6618 private void readGrantedPermissionsLP(XmlPullParser parser,
6619 HashSet<String> outPerms) throws IOException, XmlPullParserException {
6620 int outerDepth = parser.getDepth();
6621 int type;
6622 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6623 && (type != XmlPullParser.END_TAG
6624 || parser.getDepth() > outerDepth)) {
6625 if (type == XmlPullParser.END_TAG
6626 || type == XmlPullParser.TEXT) {
6627 continue;
6628 }
6629
6630 String tagName = parser.getName();
6631 if (tagName.equals("item")) {
6632 String name = parser.getAttributeValue(null, "name");
6633 if (name != null) {
6634 outPerms.add(name.intern());
6635 } else {
6636 reportSettingsProblem(Log.WARN,
6637 "Error in package manager settings: <perms> has"
6638 + " no name at " + parser.getPositionDescription());
6639 }
6640 } else {
6641 reportSettingsProblem(Log.WARN,
6642 "Unknown element under <perms>: "
6643 + parser.getName());
6644 }
6645 XmlUtils.skipCurrentTag(parser);
6646 }
6647 }
6648
6649 private void readPreferredPackagesLP(XmlPullParser parser)
6650 throws XmlPullParserException, IOException {
6651 int outerDepth = parser.getDepth();
6652 int type;
6653 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6654 && (type != XmlPullParser.END_TAG
6655 || parser.getDepth() > outerDepth)) {
6656 if (type == XmlPullParser.END_TAG
6657 || type == XmlPullParser.TEXT) {
6658 continue;
6659 }
6660
6661 String tagName = parser.getName();
6662 if (tagName.equals("item")) {
6663 String name = parser.getAttributeValue(null, "name");
6664 if (name != null) {
6665 mPendingPreferredPackages.add(name);
6666 } else {
6667 reportSettingsProblem(Log.WARN,
6668 "Error in package manager settings: <preferred-package> has no name at "
6669 + parser.getPositionDescription());
6670 }
6671 } else {
6672 reportSettingsProblem(Log.WARN,
6673 "Unknown element under <preferred-packages>: "
6674 + parser.getName());
6675 }
6676 XmlUtils.skipCurrentTag(parser);
6677 }
6678 }
6679
6680 private void readPreferredActivitiesLP(XmlPullParser parser)
6681 throws XmlPullParserException, IOException {
6682 int outerDepth = parser.getDepth();
6683 int type;
6684 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6685 && (type != XmlPullParser.END_TAG
6686 || parser.getDepth() > outerDepth)) {
6687 if (type == XmlPullParser.END_TAG
6688 || type == XmlPullParser.TEXT) {
6689 continue;
6690 }
6691
6692 String tagName = parser.getName();
6693 if (tagName.equals("item")) {
6694 PreferredActivity pa = new PreferredActivity(parser);
6695 if (pa.mParseError == null) {
6696 mPreferredActivities.addFilter(pa);
6697 } else {
6698 reportSettingsProblem(Log.WARN,
6699 "Error in package manager settings: <preferred-activity> "
6700 + pa.mParseError + " at "
6701 + parser.getPositionDescription());
6702 }
6703 } else {
6704 reportSettingsProblem(Log.WARN,
6705 "Unknown element under <preferred-activities>: "
6706 + parser.getName());
6707 XmlUtils.skipCurrentTag(parser);
6708 }
6709 }
6710 }
6711
6712 // Returns -1 if we could not find an available UserId to assign
6713 private int newUserIdLP(Object obj) {
6714 // Let's be stupidly inefficient for now...
6715 final int N = mUserIds.size();
6716 for (int i=0; i<N; i++) {
6717 if (mUserIds.get(i) == null) {
6718 mUserIds.set(i, obj);
6719 return FIRST_APPLICATION_UID + i;
6720 }
6721 }
6722
6723 // None left?
6724 if (N >= MAX_APPLICATION_UIDS) {
6725 return -1;
6726 }
6727
6728 mUserIds.add(obj);
6729 return FIRST_APPLICATION_UID + N;
6730 }
6731
6732 public PackageSetting getDisabledSystemPkg(String name) {
6733 synchronized(mPackages) {
6734 PackageSetting ps = mDisabledSysPackages.get(name);
6735 return ps;
6736 }
6737 }
6738
6739 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
6740 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
6741 if (Config.LOGV) {
6742 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
6743 + " componentName = " + componentInfo.name);
6744 Log.v(TAG, "enabledComponents: "
6745 + Arrays.toString(packageSettings.enabledComponents.toArray()));
6746 Log.v(TAG, "disabledComponents: "
6747 + Arrays.toString(packageSettings.disabledComponents.toArray()));
6748 }
6749 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
6750 || ((componentInfo.enabled
6751 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
6752 || (componentInfo.applicationInfo.enabled
6753 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
6754 && !packageSettings.disabledComponents.contains(componentInfo.name))
6755 || packageSettings.enabledComponents.contains(componentInfo.name));
6756 }
6757 }
6758}