blob: 237b70d3f448bf3bea55de183e68f94fc921bebf [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
1621 public void querySyncProviders(List outNames, List outInfo) {
1622 synchronized (mPackages) {
1623 Iterator<Map.Entry<String, PackageParser.Provider>> i
1624 = mProviders.entrySet().iterator();
1625
1626 while (i.hasNext()) {
1627 Map.Entry<String, PackageParser.Provider> entry = i.next();
1628 PackageParser.Provider p = entry.getValue();
1629
1630 if (p.syncable
1631 && (!mSafeMode || (p.info.applicationInfo.flags
1632 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1633 outNames.add(entry.getKey());
1634 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1635 }
1636 }
1637 }
1638 }
1639
1640 public List<ProviderInfo> queryContentProviders(String processName,
1641 int uid, int flags) {
1642 ArrayList<ProviderInfo> finalList = null;
1643
1644 synchronized (mPackages) {
1645 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1646 while (i.hasNext()) {
1647 PackageParser.Provider p = i.next();
1648 if (p.info.authority != null
1649 && (processName == null ||
1650 (p.info.processName.equals(processName)
1651 && p.info.applicationInfo.uid == uid))
1652 && mSettings.isEnabledLP(p.info, flags)
1653 && (!mSafeMode || (p.info.applicationInfo.flags
1654 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1655 if (finalList == null) {
1656 finalList = new ArrayList<ProviderInfo>(3);
1657 }
1658 finalList.add(PackageParser.generateProviderInfo(p,
1659 flags));
1660 }
1661 }
1662 }
1663
1664 if (finalList != null) {
1665 Collections.sort(finalList, mProviderInitOrderSorter);
1666 }
1667
1668 return finalList;
1669 }
1670
1671 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1672 int flags) {
1673 synchronized (mPackages) {
1674 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1675 return PackageParser.generateInstrumentationInfo(i, flags);
1676 }
1677 }
1678
1679 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1680 int flags) {
1681 ArrayList<InstrumentationInfo> finalList =
1682 new ArrayList<InstrumentationInfo>();
1683
1684 synchronized (mPackages) {
1685 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1686 while (i.hasNext()) {
1687 PackageParser.Instrumentation p = i.next();
1688 if (targetPackage == null
1689 || targetPackage.equals(p.info.targetPackage)) {
1690 finalList.add(PackageParser.generateInstrumentationInfo(p,
1691 flags));
1692 }
1693 }
1694 }
1695
1696 return finalList;
1697 }
1698
1699 private void scanDirLI(File dir, int flags, int scanMode) {
1700 Log.d(TAG, "Scanning app dir " + dir);
1701
1702 String[] files = dir.list();
1703
1704 int i;
1705 for (i=0; i<files.length; i++) {
1706 File file = new File(dir, files[i]);
1707 PackageParser.Package pkg = scanPackageLI(file, file, file,
1708 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1709 }
1710 }
1711
1712 private static void reportSettingsProblem(int priority, String msg) {
1713 try {
1714 File dataDir = Environment.getDataDirectory();
1715 File systemDir = new File(dataDir, "system");
1716 File fname = new File(systemDir, "uiderrors.txt");
1717 FileOutputStream out = new FileOutputStream(fname, true);
1718 PrintWriter pw = new PrintWriter(out);
1719 pw.println(msg);
1720 pw.close();
1721 FileUtils.setPermissions(
1722 fname.toString(),
1723 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1724 -1, -1);
1725 } catch (java.io.IOException e) {
1726 }
1727 Log.println(priority, TAG, msg);
1728 }
1729
1730 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1731 PackageParser.Package pkg, File srcFile, int parseFlags) {
1732 if (GET_CERTIFICATES) {
1733 if (ps == null || !ps.codePath.equals(srcFile)
1734 || ps.getTimeStamp() != srcFile.lastModified()) {
1735 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1736 if (!pp.collectCertificates(pkg, parseFlags)) {
1737 mLastScanError = pp.getParseError();
1738 return false;
1739 }
1740 }
1741 }
1742 return true;
1743 }
1744
1745 /*
1746 * Scan a package and return the newly parsed package.
1747 * Returns null in case of errors and the error code is stored in mLastScanError
1748 */
1749 private PackageParser.Package scanPackageLI(File scanFile,
1750 File destCodeFile, File destResourceFile, int parseFlags,
1751 int scanMode) {
1752 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1753 parseFlags |= mDefParseFlags;
1754 PackageParser pp = new PackageParser(scanFile.getPath());
1755 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07001756 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 final PackageParser.Package pkg = pp.parsePackage(scanFile,
1758 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
1759 if (pkg == null) {
1760 mLastScanError = pp.getParseError();
1761 return null;
1762 }
1763 PackageSetting ps;
1764 PackageSetting updatedPkg;
1765 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001766 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
1768 }
1769 if (updatedPkg != null) {
1770 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
1771 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
1772 }
1773 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1774 // Check for updated system applications here
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001775 if (updatedPkg != null) {
1776 if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
1777 if (pkg.mVersionCode <= ps.versionCode) {
1778 // The system package has been updated and the code path does not match
1779 // Ignore entry. Just return
1780 Log.w(TAG, "Package:" + pkg.packageName +
1781 " has been updated. Ignoring the one from path:"+scanFile);
1782 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1783 return null;
1784 } else {
1785 // Delete the older apk pointed to by ps
1786 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
1787 mSettings.enableSystemPackageLP(ps.name);
1788 }
1789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 }
1791 }
1792 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
1793 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
1794 return null;
1795 }
1796 // The apk is forward locked (not public) if its code and resources
1797 // are kept in different files.
1798 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
1799 scanMode |= SCAN_FORWARD_LOCKED;
1800 }
1801 // Note that we invoke the following method only if we are about to unpack an application
1802 return scanPackageLI(scanFile, destCodeFile, destResourceFile,
1803 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
1804 }
1805
1806 private static String fixProcessName(String defProcessName,
1807 String processName, int uid) {
1808 if (processName == null) {
1809 return defProcessName;
1810 }
1811 return processName;
1812 }
1813
1814 private boolean verifySignaturesLP(PackageSetting pkgSetting,
1815 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
1816 if (pkg.mSignatures != null) {
1817 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
1818 updateSignature)) {
1819 Log.e(TAG, "Package " + pkg.packageName
1820 + " signatures do not match the previously installed version; ignoring!");
1821 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1822 return false;
1823 }
1824
1825 if (pkgSetting.sharedUser != null) {
1826 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1827 pkg.mSignatures, updateSignature)) {
1828 Log.e(TAG, "Package " + pkg.packageName
1829 + " has no signatures that match those in shared user "
1830 + pkgSetting.sharedUser.name + "; ignoring!");
1831 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
1832 return false;
1833 }
1834 }
1835 } else {
1836 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1837 }
1838 return true;
1839 }
1840
1841 private PackageParser.Package scanPackageLI(
1842 File scanFile, File destCodeFile, File destResourceFile,
1843 PackageParser.Package pkg, int parseFlags, int scanMode) {
1844
1845 mScanningPath = scanFile;
1846 if (pkg == null) {
1847 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1848 return null;
1849 }
1850
1851 final String pkgName = pkg.applicationInfo.packageName;
1852 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1853 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
1854 }
1855
1856 if (pkgName.equals("android")) {
1857 synchronized (mPackages) {
1858 if (mAndroidApplication != null) {
1859 Log.w(TAG, "*************************************************");
1860 Log.w(TAG, "Core android package being redefined. Skipping.");
1861 Log.w(TAG, " file=" + mScanningPath);
1862 Log.w(TAG, "*************************************************");
1863 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1864 return null;
1865 }
1866
1867 // Set up information for our fall-back user intent resolution
1868 // activity.
1869 mPlatformPackage = pkg;
1870 pkg.mVersionCode = mSdkVersion;
1871 mAndroidApplication = pkg.applicationInfo;
1872 mResolveActivity.applicationInfo = mAndroidApplication;
1873 mResolveActivity.name = ResolverActivity.class.getName();
1874 mResolveActivity.packageName = mAndroidApplication.packageName;
1875 mResolveActivity.processName = mAndroidApplication.processName;
1876 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1877 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1878 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
1879 mResolveActivity.exported = true;
1880 mResolveActivity.enabled = true;
1881 mResolveInfo.activityInfo = mResolveActivity;
1882 mResolveInfo.priority = 0;
1883 mResolveInfo.preferredOrder = 0;
1884 mResolveInfo.match = 0;
1885 mResolveComponentName = new ComponentName(
1886 mAndroidApplication.packageName, mResolveActivity.name);
1887 }
1888 }
1889
1890 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
1891 TAG, "Scanning package " + pkgName);
1892 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
1893 Log.w(TAG, "*************************************************");
1894 Log.w(TAG, "Application package " + pkgName
1895 + " already installed. Skipping duplicate.");
1896 Log.w(TAG, "*************************************************");
1897 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1898 return null;
1899 }
1900
1901 SharedUserSetting suid = null;
1902 PackageSetting pkgSetting = null;
1903
1904 boolean removeExisting = false;
1905
1906 synchronized (mPackages) {
1907 // Check all shared libraries and map to their actual file path.
1908 if (pkg.usesLibraryFiles != null) {
1909 for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
1910 String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
1911 if (file == null) {
1912 Log.e(TAG, "Package " + pkg.packageName
1913 + " requires unavailable shared library "
1914 + pkg.usesLibraryFiles[i] + "; ignoring!");
1915 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
1916 return null;
1917 }
1918 pkg.usesLibraryFiles[i] = file;
1919 }
1920 }
1921
1922 if (pkg.mSharedUserId != null) {
1923 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
1924 pkg.applicationInfo.flags, true);
1925 if (suid == null) {
1926 Log.w(TAG, "Creating application package " + pkgName
1927 + " for shared user failed");
1928 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1929 return null;
1930 }
1931 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
1932 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
1933 + suid.userId + "): packages=" + suid.packages);
1934 }
1935 }
1936
1937 // Just create the setting, don't add it yet
1938 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
1939 destResourceFile, pkg.applicationInfo.flags, true, false);
1940 if (pkgSetting == null) {
1941 Log.w(TAG, "Creating application package " + pkgName + " failed");
1942 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1943 return null;
1944 }
1945 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
1946 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
1947 }
1948
1949 pkg.applicationInfo.uid = pkgSetting.userId;
1950 pkg.mExtras = pkgSetting;
1951
1952 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
1953 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
1954 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
1955 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1956 return null;
1957 }
1958 // The signature has changed, but this package is in the system
1959 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07001960 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 // However... if this package is part of a shared user, but it
1962 // doesn't match the signature of the shared user, let's fail.
1963 // What this means is that you can't change the signatures
1964 // associated with an overall shared user, which doesn't seem all
1965 // that unreasonable.
1966 if (pkgSetting.sharedUser != null) {
1967 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1968 pkg.mSignatures, false)) {
1969 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
1970 return null;
1971 }
1972 }
1973 removeExisting = true;
1974 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001975
1976 // Verify that this new package doesn't have any content providers
1977 // that conflict with existing packages. Only do this if the
1978 // package isn't already installed, since we don't want to break
1979 // things that are installed.
1980 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
1981 int N = pkg.providers.size();
1982 int i;
1983 for (i=0; i<N; i++) {
1984 PackageParser.Provider p = pkg.providers.get(i);
1985 String names[] = p.info.authority.split(";");
1986 for (int j = 0; j < names.length; j++) {
1987 if (mProviders.containsKey(names[j])) {
1988 PackageParser.Provider other = mProviders.get(names[j]);
1989 Log.w(TAG, "Can't install because provider name " + names[j] +
1990 " (in package " + pkg.applicationInfo.packageName +
1991 ") is already used by "
1992 + ((other != null && other.component != null)
1993 ? other.component.getPackageName() : "?"));
1994 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
1995 return null;
1996 }
1997 }
1998 }
1999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 }
2001
2002 if (removeExisting) {
2003 if (mInstaller != null) {
2004 int ret = mInstaller.remove(pkgName);
2005 if (ret != 0) {
2006 String msg = "System package " + pkg.packageName
2007 + " could not have data directory erased after signature change.";
2008 reportSettingsProblem(Log.WARN, msg);
2009 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2010 return null;
2011 }
2012 }
2013 Log.w(TAG, "System package " + pkg.packageName
2014 + " signature changed: existing data removed.");
2015 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2016 }
2017
2018 long scanFileTime = scanFile.lastModified();
2019 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2020 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2021 pkg.applicationInfo.processName = fixProcessName(
2022 pkg.applicationInfo.packageName,
2023 pkg.applicationInfo.processName,
2024 pkg.applicationInfo.uid);
2025 pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
2026
2027 File dataPath;
2028 if (mPlatformPackage == pkg) {
2029 // The system package is special.
2030 dataPath = new File (Environment.getDataDirectory(), "system");
2031 pkg.applicationInfo.dataDir = dataPath.getPath();
2032 } else {
2033 // This is a normal package, need to make its data directory.
2034 dataPath = new File(mAppDataDir, pkgName);
2035 if (dataPath.exists()) {
2036 mOutPermissions[1] = 0;
2037 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2038 if (mOutPermissions[1] == pkg.applicationInfo.uid
2039 || !Process.supportsProcesses()) {
2040 pkg.applicationInfo.dataDir = dataPath.getPath();
2041 } else {
2042 boolean recovered = false;
2043 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2044 // If this is a system app, we can at least delete its
2045 // current data so the application will still work.
2046 if (mInstaller != null) {
2047 int ret = mInstaller.remove(pkgName);
2048 if(ret >= 0) {
2049 // Old data gone!
2050 String msg = "System package " + pkg.packageName
2051 + " has changed from uid: "
2052 + mOutPermissions[1] + " to "
2053 + pkg.applicationInfo.uid + "; old data erased";
2054 reportSettingsProblem(Log.WARN, msg);
2055 recovered = true;
2056
2057 // And now re-install the app.
2058 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2059 pkg.applicationInfo.uid);
2060 if (ret == -1) {
2061 // Ack should not happen!
2062 msg = "System package " + pkg.packageName
2063 + " could not have data directory re-created after delete.";
2064 reportSettingsProblem(Log.WARN, msg);
2065 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2066 return null;
2067 }
2068 }
2069 }
2070 if (!recovered) {
2071 mHasSystemUidErrors = true;
2072 }
2073 }
2074 if (!recovered) {
2075 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2076 + pkg.applicationInfo.uid + "/fs_"
2077 + mOutPermissions[1];
2078 String msg = "Package " + pkg.packageName
2079 + " has mismatched uid: "
2080 + mOutPermissions[1] + " on disk, "
2081 + pkg.applicationInfo.uid + " in settings";
2082 synchronized (mPackages) {
2083 if (!mReportedUidError) {
2084 mReportedUidError = true;
2085 msg = msg + "; read messages:\n"
2086 + mSettings.getReadMessagesLP();
2087 }
2088 reportSettingsProblem(Log.ERROR, msg);
2089 }
2090 }
2091 }
2092 pkg.applicationInfo.dataDir = dataPath.getPath();
2093 } else {
2094 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2095 Log.v(TAG, "Want this data dir: " + dataPath);
2096 //invoke installer to do the actual installation
2097 if (mInstaller != null) {
2098 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2099 pkg.applicationInfo.uid);
2100 if(ret < 0) {
2101 // Error from installer
2102 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2103 return null;
2104 }
2105 } else {
2106 dataPath.mkdirs();
2107 if (dataPath.exists()) {
2108 FileUtils.setPermissions(
2109 dataPath.toString(),
2110 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2111 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2112 }
2113 }
2114 if (dataPath.exists()) {
2115 pkg.applicationInfo.dataDir = dataPath.getPath();
2116 } else {
2117 Log.w(TAG, "Unable to create data directory: " + dataPath);
2118 pkg.applicationInfo.dataDir = null;
2119 }
2120 }
2121 }
2122
2123 // Perform shared library installation and dex validation and
2124 // optimization, if this is not a system app.
2125 if (mInstaller != null) {
2126 String path = scanFile.getPath();
2127 if (scanFileNewer) {
2128 Log.i(TAG, path + " changed; unpacking");
2129 try {
2130 cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2131 } catch (IOException e) {
2132 Log.e(TAG, "Failure extracting shared libs", e);
2133 if(mInstaller != null) {
2134 mInstaller.remove(pkgName);
2135 } else {
2136 dataPath.delete();
2137 }
2138 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2139 return null;
2140 }
2141 }
2142
2143 if ((scanMode&SCAN_NO_DEX) == 0
2144 && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
2145 int ret = 0;
2146 try {
2147 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2148 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2149 (scanMode&SCAN_FORWARD_LOCKED) == 0);
2150 }
2151 } catch (FileNotFoundException e) {
2152 Log.w(TAG, "Apk not found for dexopt: " + path);
2153 ret = -1;
2154 } catch (IOException e) {
2155 Log.w(TAG, "Exception reading apk: " + path, e);
2156 ret = -1;
2157 }
2158 if (ret < 0) {
2159 //error from installer
2160 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2161 return null;
2162 }
2163 }
2164 }
2165
2166 if (mFactoryTest && pkg.requestedPermissions.contains(
2167 android.Manifest.permission.FACTORY_TEST)) {
2168 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2169 }
2170
2171 if ((scanMode&SCAN_MONITOR) != 0) {
2172 pkg.mPath = destCodeFile.getAbsolutePath();
2173 mAppDirs.put(pkg.mPath, pkg);
2174 }
2175
2176 synchronized (mPackages) {
2177 // We don't expect installation to fail beyond this point
2178 // Add the new setting to mSettings
2179 mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
2180 // Add the new setting to mPackages
2181 mPackages.put(pkg.applicationInfo.packageName, pkg);
2182 int N = pkg.providers.size();
2183 StringBuilder r = null;
2184 int i;
2185 for (i=0; i<N; i++) {
2186 PackageParser.Provider p = pkg.providers.get(i);
2187 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2188 p.info.processName, pkg.applicationInfo.uid);
2189 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2190 p.info.name), p);
2191 p.syncable = p.info.isSyncable;
2192 String names[] = p.info.authority.split(";");
2193 p.info.authority = null;
2194 for (int j = 0; j < names.length; j++) {
2195 if (j == 1 && p.syncable) {
2196 // We only want the first authority for a provider to possibly be
2197 // syncable, so if we already added this provider using a different
2198 // authority clear the syncable flag. We copy the provider before
2199 // changing it because the mProviders object contains a reference
2200 // to a provider that we don't want to change.
2201 // Only do this for the second authority since the resulting provider
2202 // object can be the same for all future authorities for this provider.
2203 p = new PackageParser.Provider(p);
2204 p.syncable = false;
2205 }
2206 if (!mProviders.containsKey(names[j])) {
2207 mProviders.put(names[j], p);
2208 if (p.info.authority == null) {
2209 p.info.authority = names[j];
2210 } else {
2211 p.info.authority = p.info.authority + ";" + names[j];
2212 }
2213 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2214 Log.d(TAG, "Registered content provider: " + names[j] +
2215 ", className = " + p.info.name +
2216 ", isSyncable = " + p.info.isSyncable);
2217 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002218 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219 Log.w(TAG, "Skipping provider name " + names[j] +
2220 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002221 "): name already used by "
2222 + ((other != null && other.component != null)
2223 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 }
2225 }
2226 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2227 if (r == null) {
2228 r = new StringBuilder(256);
2229 } else {
2230 r.append(' ');
2231 }
2232 r.append(p.info.name);
2233 }
2234 }
2235 if (r != null) {
2236 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2237 }
2238
2239 N = pkg.services.size();
2240 r = null;
2241 for (i=0; i<N; i++) {
2242 PackageParser.Service s = pkg.services.get(i);
2243 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2244 s.info.processName, pkg.applicationInfo.uid);
2245 mServices.addService(s);
2246 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2247 if (r == null) {
2248 r = new StringBuilder(256);
2249 } else {
2250 r.append(' ');
2251 }
2252 r.append(s.info.name);
2253 }
2254 }
2255 if (r != null) {
2256 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2257 }
2258
2259 N = pkg.receivers.size();
2260 r = null;
2261 for (i=0; i<N; i++) {
2262 PackageParser.Activity a = pkg.receivers.get(i);
2263 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2264 a.info.processName, pkg.applicationInfo.uid);
2265 mReceivers.addActivity(a, "receiver");
2266 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2267 if (r == null) {
2268 r = new StringBuilder(256);
2269 } else {
2270 r.append(' ');
2271 }
2272 r.append(a.info.name);
2273 }
2274 }
2275 if (r != null) {
2276 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2277 }
2278
2279 N = pkg.activities.size();
2280 r = null;
2281 for (i=0; i<N; i++) {
2282 PackageParser.Activity a = pkg.activities.get(i);
2283 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2284 a.info.processName, pkg.applicationInfo.uid);
2285 mActivities.addActivity(a, "activity");
2286 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2287 if (r == null) {
2288 r = new StringBuilder(256);
2289 } else {
2290 r.append(' ');
2291 }
2292 r.append(a.info.name);
2293 }
2294 }
2295 if (r != null) {
2296 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2297 }
2298
2299 N = pkg.permissionGroups.size();
2300 r = null;
2301 for (i=0; i<N; i++) {
2302 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2303 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2304 if (cur == null) {
2305 mPermissionGroups.put(pg.info.name, pg);
2306 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2307 if (r == null) {
2308 r = new StringBuilder(256);
2309 } else {
2310 r.append(' ');
2311 }
2312 r.append(pg.info.name);
2313 }
2314 } else {
2315 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2316 + pg.info.packageName + " ignored: original from "
2317 + cur.info.packageName);
2318 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2319 if (r == null) {
2320 r = new StringBuilder(256);
2321 } else {
2322 r.append(' ');
2323 }
2324 r.append("DUP:");
2325 r.append(pg.info.name);
2326 }
2327 }
2328 }
2329 if (r != null) {
2330 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2331 }
2332
2333 N = pkg.permissions.size();
2334 r = null;
2335 for (i=0; i<N; i++) {
2336 PackageParser.Permission p = pkg.permissions.get(i);
2337 HashMap<String, BasePermission> permissionMap =
2338 p.tree ? mSettings.mPermissionTrees
2339 : mSettings.mPermissions;
2340 p.group = mPermissionGroups.get(p.info.group);
2341 if (p.info.group == null || p.group != null) {
2342 BasePermission bp = permissionMap.get(p.info.name);
2343 if (bp == null) {
2344 bp = new BasePermission(p.info.name, p.info.packageName,
2345 BasePermission.TYPE_NORMAL);
2346 permissionMap.put(p.info.name, bp);
2347 }
2348 if (bp.perm == null) {
2349 if (bp.sourcePackage == null
2350 || bp.sourcePackage.equals(p.info.packageName)) {
2351 BasePermission tree = findPermissionTreeLP(p.info.name);
2352 if (tree == null
2353 || tree.sourcePackage.equals(p.info.packageName)) {
2354 bp.perm = p;
2355 bp.uid = pkg.applicationInfo.uid;
2356 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2357 if (r == null) {
2358 r = new StringBuilder(256);
2359 } else {
2360 r.append(' ');
2361 }
2362 r.append(p.info.name);
2363 }
2364 } else {
2365 Log.w(TAG, "Permission " + p.info.name + " from package "
2366 + p.info.packageName + " ignored: base tree "
2367 + tree.name + " is from package "
2368 + tree.sourcePackage);
2369 }
2370 } else {
2371 Log.w(TAG, "Permission " + p.info.name + " from package "
2372 + p.info.packageName + " ignored: original from "
2373 + bp.sourcePackage);
2374 }
2375 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2376 if (r == null) {
2377 r = new StringBuilder(256);
2378 } else {
2379 r.append(' ');
2380 }
2381 r.append("DUP:");
2382 r.append(p.info.name);
2383 }
2384 } else {
2385 Log.w(TAG, "Permission " + p.info.name + " from package "
2386 + p.info.packageName + " ignored: no group "
2387 + p.group);
2388 }
2389 }
2390 if (r != null) {
2391 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2392 }
2393
2394 N = pkg.instrumentation.size();
2395 r = null;
2396 for (i=0; i<N; i++) {
2397 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2398 a.info.packageName = pkg.applicationInfo.packageName;
2399 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2400 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2401 a.info.dataDir = pkg.applicationInfo.dataDir;
2402 mInstrumentation.put(a.component, a);
2403 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2404 if (r == null) {
2405 r = new StringBuilder(256);
2406 } else {
2407 r.append(' ');
2408 }
2409 r.append(a.info.name);
2410 }
2411 }
2412 if (r != null) {
2413 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2414 }
2415
2416 pkgSetting.setTimeStamp(scanFileTime);
2417 }
2418
2419 return pkg;
2420 }
2421
2422 private void cachePackageSharedLibsLI(PackageParser.Package pkg,
2423 File dataPath, File scanFile) throws IOException {
2424 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2425 final String sharedLibraryABI = "armeabi";
2426 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2427 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2428 final String sharedLibrarySuffix = ".so";
2429 boolean createdSharedLib = false;
2430 try {
2431 ZipFile zipFile = new ZipFile(scanFile);
2432 Enumeration<ZipEntry> entries =
2433 (Enumeration<ZipEntry>) zipFile.entries();
2434
2435 while (entries.hasMoreElements()) {
2436 ZipEntry entry = entries.nextElement();
2437 if (entry.isDirectory()) {
2438 continue;
2439 }
2440 String entryName = entry.getName();
2441 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2442 && entryName.endsWith(sharedLibrarySuffix))) {
2443 continue;
2444 }
2445 String libFileName = entryName.substring(
2446 apkLibraryDirectory.length());
2447 if (libFileName.contains("/")
2448 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2449 continue;
2450 }
2451 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2452 File.separator + libFileName;
2453 File sharedLibraryFile = new File(sharedLibraryFilePath);
2454 if (! sharedLibraryFile.exists() ||
2455 sharedLibraryFile.length() != entry.getSize() ||
2456 sharedLibraryFile.lastModified() != entry.getTime()) {
2457 if (Config.LOGD) {
2458 Log.d(TAG, "Caching shared lib " + entry.getName());
2459 }
2460 if (mInstaller == null) {
2461 sharedLibraryDir.mkdir();
2462 createdSharedLib = true;
2463 }
2464 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2465 sharedLibraryFile);
2466 }
2467 }
2468 } catch (IOException e) {
2469 Log.e(TAG, "Failed to cache package shared libs", e);
2470 if(createdSharedLib) {
2471 sharedLibraryDir.delete();
2472 }
2473 throw e;
2474 }
2475 }
2476
2477 private void cacheSharedLibLI(PackageParser.Package pkg,
2478 ZipFile zipFile, ZipEntry entry,
2479 File sharedLibraryDir,
2480 File sharedLibraryFile) throws IOException {
2481 InputStream inputStream = zipFile.getInputStream(entry);
2482 try {
2483 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2484 String tempFilePath = tempFile.getPath();
2485 // XXX package manager can't change owner, so the lib files for
2486 // now need to be left as world readable and owned by the system.
2487 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2488 ! tempFile.setLastModified(entry.getTime()) ||
2489 FileUtils.setPermissions(tempFilePath,
2490 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2491 |FileUtils.S_IROTH, -1, -1) != 0 ||
2492 ! tempFile.renameTo(sharedLibraryFile)) {
2493 // Failed to properly write file.
2494 tempFile.delete();
2495 throw new IOException("Couldn't create cached shared lib "
2496 + sharedLibraryFile + " in " + sharedLibraryDir);
2497 }
2498 } finally {
2499 inputStream.close();
2500 }
2501 }
2502
2503 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2504 if (chatty && Config.LOGD) Log.d(
2505 TAG, "Removing package " + pkg.applicationInfo.packageName );
2506
2507 synchronized (mPackages) {
2508 if (pkg.mPreferredOrder > 0) {
2509 mSettings.mPreferredPackages.remove(pkg);
2510 pkg.mPreferredOrder = 0;
2511 updatePreferredIndicesLP();
2512 }
2513
2514 clearPackagePreferredActivitiesLP(pkg.packageName);
2515
2516 mPackages.remove(pkg.applicationInfo.packageName);
2517 if (pkg.mPath != null) {
2518 mAppDirs.remove(pkg.mPath);
2519 }
2520
2521 PackageSetting ps = (PackageSetting)pkg.mExtras;
2522 if (ps != null && ps.sharedUser != null) {
2523 // XXX don't do this until the data is removed.
2524 if (false) {
2525 ps.sharedUser.packages.remove(ps);
2526 if (ps.sharedUser.packages.size() == 0) {
2527 // Remove.
2528 }
2529 }
2530 }
2531
2532 int N = pkg.providers.size();
2533 StringBuilder r = null;
2534 int i;
2535 for (i=0; i<N; i++) {
2536 PackageParser.Provider p = pkg.providers.get(i);
2537 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2538 p.info.name));
2539 if (p.info.authority == null) {
2540
2541 /* The is another ContentProvider with this authority when
2542 * this app was installed so this authority is null,
2543 * Ignore it as we don't have to unregister the provider.
2544 */
2545 continue;
2546 }
2547 String names[] = p.info.authority.split(";");
2548 for (int j = 0; j < names.length; j++) {
2549 if (mProviders.get(names[j]) == p) {
2550 mProviders.remove(names[j]);
2551 if (chatty && Config.LOGD) Log.d(
2552 TAG, "Unregistered content provider: " + names[j] +
2553 ", className = " + p.info.name +
2554 ", isSyncable = " + p.info.isSyncable);
2555 }
2556 }
2557 if (chatty) {
2558 if (r == null) {
2559 r = new StringBuilder(256);
2560 } else {
2561 r.append(' ');
2562 }
2563 r.append(p.info.name);
2564 }
2565 }
2566 if (r != null) {
2567 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2568 }
2569
2570 N = pkg.services.size();
2571 r = null;
2572 for (i=0; i<N; i++) {
2573 PackageParser.Service s = pkg.services.get(i);
2574 mServices.removeService(s);
2575 if (chatty) {
2576 if (r == null) {
2577 r = new StringBuilder(256);
2578 } else {
2579 r.append(' ');
2580 }
2581 r.append(s.info.name);
2582 }
2583 }
2584 if (r != null) {
2585 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2586 }
2587
2588 N = pkg.receivers.size();
2589 r = null;
2590 for (i=0; i<N; i++) {
2591 PackageParser.Activity a = pkg.receivers.get(i);
2592 mReceivers.removeActivity(a, "receiver");
2593 if (chatty) {
2594 if (r == null) {
2595 r = new StringBuilder(256);
2596 } else {
2597 r.append(' ');
2598 }
2599 r.append(a.info.name);
2600 }
2601 }
2602 if (r != null) {
2603 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2604 }
2605
2606 N = pkg.activities.size();
2607 r = null;
2608 for (i=0; i<N; i++) {
2609 PackageParser.Activity a = pkg.activities.get(i);
2610 mActivities.removeActivity(a, "activity");
2611 if (chatty) {
2612 if (r == null) {
2613 r = new StringBuilder(256);
2614 } else {
2615 r.append(' ');
2616 }
2617 r.append(a.info.name);
2618 }
2619 }
2620 if (r != null) {
2621 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2622 }
2623
2624 N = pkg.permissions.size();
2625 r = null;
2626 for (i=0; i<N; i++) {
2627 PackageParser.Permission p = pkg.permissions.get(i);
2628 boolean tree = false;
2629 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2630 if (bp == null) {
2631 tree = true;
2632 bp = mSettings.mPermissionTrees.get(p.info.name);
2633 }
2634 if (bp != null && bp.perm == p) {
2635 if (bp.type != BasePermission.TYPE_BUILTIN) {
2636 if (tree) {
2637 mSettings.mPermissionTrees.remove(p.info.name);
2638 } else {
2639 mSettings.mPermissions.remove(p.info.name);
2640 }
2641 } else {
2642 bp.perm = null;
2643 }
2644 if (chatty) {
2645 if (r == null) {
2646 r = new StringBuilder(256);
2647 } else {
2648 r.append(' ');
2649 }
2650 r.append(p.info.name);
2651 }
2652 }
2653 }
2654 if (r != null) {
2655 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2656 }
2657
2658 N = pkg.instrumentation.size();
2659 r = null;
2660 for (i=0; i<N; i++) {
2661 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2662 mInstrumentation.remove(a.component);
2663 if (chatty) {
2664 if (r == null) {
2665 r = new StringBuilder(256);
2666 } else {
2667 r.append(' ');
2668 }
2669 r.append(a.info.name);
2670 }
2671 }
2672 if (r != null) {
2673 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2674 }
2675 }
2676 }
2677
2678 private static final boolean isPackageFilename(String name) {
2679 return name != null && name.endsWith(".apk");
2680 }
2681
2682 private void updatePermissionsLP() {
2683 // Make sure there are no dangling permission trees.
2684 Iterator<BasePermission> it = mSettings.mPermissionTrees
2685 .values().iterator();
2686 while (it.hasNext()) {
2687 BasePermission bp = it.next();
2688 if (bp.perm == null) {
2689 Log.w(TAG, "Removing dangling permission tree: " + bp.name
2690 + " from package " + bp.sourcePackage);
2691 it.remove();
2692 }
2693 }
2694
2695 // Make sure all dynamic permissions have been assigned to a package,
2696 // and make sure there are no dangling permissions.
2697 it = mSettings.mPermissions.values().iterator();
2698 while (it.hasNext()) {
2699 BasePermission bp = it.next();
2700 if (bp.type == BasePermission.TYPE_DYNAMIC) {
2701 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
2702 + bp.name + " pkg=" + bp.sourcePackage
2703 + " info=" + bp.pendingInfo);
2704 if (bp.perm == null && bp.pendingInfo != null) {
2705 BasePermission tree = findPermissionTreeLP(bp.name);
2706 if (tree != null) {
2707 bp.perm = new PackageParser.Permission(tree.perm.owner,
2708 new PermissionInfo(bp.pendingInfo));
2709 bp.perm.info.packageName = tree.perm.info.packageName;
2710 bp.perm.info.name = bp.name;
2711 bp.uid = tree.uid;
2712 }
2713 }
2714 }
2715 if (bp.perm == null) {
2716 Log.w(TAG, "Removing dangling permission: " + bp.name
2717 + " from package " + bp.sourcePackage);
2718 it.remove();
2719 }
2720 }
2721
2722 // Now update the permissions for all packages, in particular
2723 // replace the granted permissions of the system packages.
2724 for (PackageParser.Package pkg : mPackages.values()) {
2725 grantPermissionsLP(pkg, false);
2726 }
2727 }
2728
2729 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
2730 final PackageSetting ps = (PackageSetting)pkg.mExtras;
2731 if (ps == null) {
2732 return;
2733 }
2734 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2735 boolean addedPermission = false;
2736
2737 if (replace) {
2738 ps.permissionsFixed = false;
2739 if (gp == ps) {
2740 gp.grantedPermissions.clear();
2741 gp.gids = mGlobalGids;
2742 }
2743 }
2744
2745 if (gp.gids == null) {
2746 gp.gids = mGlobalGids;
2747 }
2748
2749 final int N = pkg.requestedPermissions.size();
2750 for (int i=0; i<N; i++) {
2751 String name = pkg.requestedPermissions.get(i);
2752 BasePermission bp = mSettings.mPermissions.get(name);
2753 PackageParser.Permission p = bp != null ? bp.perm : null;
2754 if (false) {
2755 if (gp != ps) {
2756 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
2757 + ": " + p);
2758 }
2759 }
2760 if (p != null) {
2761 final String perm = p.info.name;
2762 boolean allowed;
2763 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
2764 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
2765 allowed = true;
2766 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
2767 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2768 allowed = (checkSignaturesLP(p.owner, pkg)
2769 == PackageManager.SIGNATURE_MATCH)
2770 || (checkSignaturesLP(mPlatformPackage, pkg)
2771 == PackageManager.SIGNATURE_MATCH);
2772 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2773 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
2774 // For updated system applications, the signatureOrSystem permission
2775 // is granted only if it had been defined by the original application.
2776 if ((pkg.applicationInfo.flags
2777 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
2778 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
2779 if(sysPs.grantedPermissions.contains(perm)) {
2780 allowed = true;
2781 } else {
2782 allowed = false;
2783 }
2784 } else {
2785 allowed = true;
2786 }
2787 }
2788 }
2789 } else {
2790 allowed = false;
2791 }
2792 if (false) {
2793 if (gp != ps) {
2794 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
2795 }
2796 }
2797 if (allowed) {
2798 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
2799 && ps.permissionsFixed) {
2800 // If this is an existing, non-system package, then
2801 // we can't add any new permissions to it.
2802 if (!gp.loadedPermissions.contains(perm)) {
2803 allowed = false;
2804 }
2805 }
2806 if (allowed) {
2807 if (!gp.grantedPermissions.contains(perm)) {
2808 addedPermission = true;
2809 gp.grantedPermissions.add(perm);
2810 gp.gids = appendInts(gp.gids, bp.gids);
2811 }
2812 } else {
2813 Log.w(TAG, "Not granting permission " + perm
2814 + " to package " + pkg.packageName
2815 + " because it was previously installed without");
2816 }
2817 } else {
2818 Log.w(TAG, "Not granting permission " + perm
2819 + " to package " + pkg.packageName
2820 + " (protectionLevel=" + p.info.protectionLevel
2821 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
2822 + ")");
2823 }
2824 } else {
2825 Log.w(TAG, "Unknown permission " + name
2826 + " in package " + pkg.packageName);
2827 }
2828 }
2829
2830 if ((addedPermission || replace) && !ps.permissionsFixed &&
2831 (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2832 // This is the first that we have heard about this package, so the
2833 // permissions we have now selected are fixed until explicitly
2834 // changed.
2835 ps.permissionsFixed = true;
2836 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
2837 }
2838 }
2839
2840 private final class ActivityIntentResolver
2841 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
2842 public List queryIntent(ContentResolver resolver, Intent intent,
2843 String resolvedType, boolean defaultOnly) {
2844 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2845 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2846 }
2847
2848 public List queryIntent(ContentResolver resolver, Intent intent,
2849 String resolvedType, int flags) {
2850 mFlags = flags;
2851 return super.queryIntent(
2852 resolver, intent, resolvedType,
2853 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2854 }
2855
2856 public final void addActivity(PackageParser.Activity a, String type) {
2857 mActivities.put(a.component, a);
2858 if (SHOW_INFO || Config.LOGV) Log.v(
2859 TAG, " " + type + " " +
2860 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2861 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2862 int NI = a.intents.size();
2863 int j;
2864 for (j=0; j<NI; j++) {
2865 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2866 if (SHOW_INFO || Config.LOGV) {
2867 Log.v(TAG, " IntentFilter:");
2868 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2869 }
2870 if (!intent.debugCheck()) {
2871 Log.w(TAG, "==> For Activity " + a.info.name);
2872 }
2873 addFilter(intent);
2874 }
2875 }
2876
2877 public final void removeActivity(PackageParser.Activity a, String type) {
2878 mActivities.remove(a.component);
2879 if (SHOW_INFO || Config.LOGV) Log.v(
2880 TAG, " " + type + " " +
2881 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2882 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2883 int NI = a.intents.size();
2884 int j;
2885 for (j=0; j<NI; j++) {
2886 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2887 if (SHOW_INFO || Config.LOGV) {
2888 Log.v(TAG, " IntentFilter:");
2889 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2890 }
2891 removeFilter(intent);
2892 }
2893 }
2894
2895 @Override
2896 protected boolean allowFilterResult(
2897 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
2898 ActivityInfo filterAi = filter.activity.info;
2899 for (int i=dest.size()-1; i>=0; i--) {
2900 ActivityInfo destAi = dest.get(i).activityInfo;
2901 if (destAi.name == filterAi.name
2902 && destAi.packageName == filterAi.packageName) {
2903 return false;
2904 }
2905 }
2906 return true;
2907 }
2908
2909 @Override
2910 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
2911 int match) {
2912 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
2913 return null;
2914 }
2915 final PackageParser.Activity activity = info.activity;
2916 if (mSafeMode && (activity.info.applicationInfo.flags
2917 &ApplicationInfo.FLAG_SYSTEM) == 0) {
2918 return null;
2919 }
2920 final ResolveInfo res = new ResolveInfo();
2921 res.activityInfo = PackageParser.generateActivityInfo(activity,
2922 mFlags);
2923 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
2924 res.filter = info;
2925 }
2926 res.priority = info.getPriority();
2927 res.preferredOrder = activity.owner.mPreferredOrder;
2928 //System.out.println("Result: " + res.activityInfo.className +
2929 // " = " + res.priority);
2930 res.match = match;
2931 res.isDefault = info.hasDefault;
2932 res.labelRes = info.labelRes;
2933 res.nonLocalizedLabel = info.nonLocalizedLabel;
2934 res.icon = info.icon;
2935 return res;
2936 }
2937
2938 @Override
2939 protected void sortResults(List<ResolveInfo> results) {
2940 Collections.sort(results, mResolvePrioritySorter);
2941 }
2942
2943 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002944 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002946 out.print(prefix); out.print(
2947 Integer.toHexString(System.identityHashCode(filter.activity)));
2948 out.print(' ');
2949 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 }
2951
2952// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
2953// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
2954// final List<ResolveInfo> retList = Lists.newArrayList();
2955// while (i.hasNext()) {
2956// final ResolveInfo resolveInfo = i.next();
2957// if (isEnabledLP(resolveInfo.activityInfo)) {
2958// retList.add(resolveInfo);
2959// }
2960// }
2961// return retList;
2962// }
2963
2964 // Keys are String (activity class name), values are Activity.
2965 private final HashMap<ComponentName, PackageParser.Activity> mActivities
2966 = new HashMap<ComponentName, PackageParser.Activity>();
2967 private int mFlags;
2968 }
2969
2970 private final class ServiceIntentResolver
2971 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
2972 public List queryIntent(ContentResolver resolver, Intent intent,
2973 String resolvedType, boolean defaultOnly) {
2974 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2975 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2976 }
2977
2978 public List queryIntent(ContentResolver resolver, Intent intent,
2979 String resolvedType, int flags) {
2980 mFlags = flags;
2981 return super.queryIntent(
2982 resolver, intent, resolvedType,
2983 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2984 }
2985
2986 public final void addService(PackageParser.Service s) {
2987 mServices.put(s.component, s);
2988 if (SHOW_INFO || Config.LOGV) Log.v(
2989 TAG, " " + (s.info.nonLocalizedLabel != null
2990 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2991 if (SHOW_INFO || Config.LOGV) Log.v(
2992 TAG, " Class=" + s.info.name);
2993 int NI = s.intents.size();
2994 int j;
2995 for (j=0; j<NI; j++) {
2996 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
2997 if (SHOW_INFO || Config.LOGV) {
2998 Log.v(TAG, " IntentFilter:");
2999 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3000 }
3001 if (!intent.debugCheck()) {
3002 Log.w(TAG, "==> For Service " + s.info.name);
3003 }
3004 addFilter(intent);
3005 }
3006 }
3007
3008 public final void removeService(PackageParser.Service s) {
3009 mServices.remove(s.component);
3010 if (SHOW_INFO || Config.LOGV) Log.v(
3011 TAG, " " + (s.info.nonLocalizedLabel != null
3012 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3013 if (SHOW_INFO || Config.LOGV) Log.v(
3014 TAG, " Class=" + s.info.name);
3015 int NI = s.intents.size();
3016 int j;
3017 for (j=0; j<NI; j++) {
3018 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3019 if (SHOW_INFO || Config.LOGV) {
3020 Log.v(TAG, " IntentFilter:");
3021 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3022 }
3023 removeFilter(intent);
3024 }
3025 }
3026
3027 @Override
3028 protected boolean allowFilterResult(
3029 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3030 ServiceInfo filterSi = filter.service.info;
3031 for (int i=dest.size()-1; i>=0; i--) {
3032 ServiceInfo destAi = dest.get(i).serviceInfo;
3033 if (destAi.name == filterSi.name
3034 && destAi.packageName == filterSi.packageName) {
3035 return false;
3036 }
3037 }
3038 return true;
3039 }
3040
3041 @Override
3042 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3043 int match) {
3044 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3045 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3046 return null;
3047 }
3048 final PackageParser.Service service = info.service;
3049 if (mSafeMode && (service.info.applicationInfo.flags
3050 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3051 return null;
3052 }
3053 final ResolveInfo res = new ResolveInfo();
3054 res.serviceInfo = PackageParser.generateServiceInfo(service,
3055 mFlags);
3056 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3057 res.filter = filter;
3058 }
3059 res.priority = info.getPriority();
3060 res.preferredOrder = service.owner.mPreferredOrder;
3061 //System.out.println("Result: " + res.activityInfo.className +
3062 // " = " + res.priority);
3063 res.match = match;
3064 res.isDefault = info.hasDefault;
3065 res.labelRes = info.labelRes;
3066 res.nonLocalizedLabel = info.nonLocalizedLabel;
3067 res.icon = info.icon;
3068 return res;
3069 }
3070
3071 @Override
3072 protected void sortResults(List<ResolveInfo> results) {
3073 Collections.sort(results, mResolvePrioritySorter);
3074 }
3075
3076 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003077 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003079 out.print(prefix); out.print(
3080 Integer.toHexString(System.identityHashCode(filter.service)));
3081 out.print(' ');
3082 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 }
3084
3085// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3086// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3087// final List<ResolveInfo> retList = Lists.newArrayList();
3088// while (i.hasNext()) {
3089// final ResolveInfo resolveInfo = (ResolveInfo) i;
3090// if (isEnabledLP(resolveInfo.serviceInfo)) {
3091// retList.add(resolveInfo);
3092// }
3093// }
3094// return retList;
3095// }
3096
3097 // Keys are String (activity class name), values are Activity.
3098 private final HashMap<ComponentName, PackageParser.Service> mServices
3099 = new HashMap<ComponentName, PackageParser.Service>();
3100 private int mFlags;
3101 };
3102
3103 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3104 new Comparator<ResolveInfo>() {
3105 public int compare(ResolveInfo r1, ResolveInfo r2) {
3106 int v1 = r1.priority;
3107 int v2 = r2.priority;
3108 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3109 if (v1 != v2) {
3110 return (v1 > v2) ? -1 : 1;
3111 }
3112 v1 = r1.preferredOrder;
3113 v2 = r2.preferredOrder;
3114 if (v1 != v2) {
3115 return (v1 > v2) ? -1 : 1;
3116 }
3117 if (r1.isDefault != r2.isDefault) {
3118 return r1.isDefault ? -1 : 1;
3119 }
3120 v1 = r1.match;
3121 v2 = r2.match;
3122 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3123 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3124 }
3125 };
3126
3127 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3128 new Comparator<ProviderInfo>() {
3129 public int compare(ProviderInfo p1, ProviderInfo p2) {
3130 final int v1 = p1.initOrder;
3131 final int v2 = p2.initOrder;
3132 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3133 }
3134 };
3135
3136 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3137 IActivityManager am = ActivityManagerNative.getDefault();
3138 if (am != null) {
3139 try {
3140 final Intent intent = new Intent(action,
3141 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3142 if (extras != null) {
3143 intent.putExtras(extras);
3144 }
3145 am.broadcastIntent(
3146 null, intent,
3147 null, null, 0, null, null, null, false, false);
3148 } catch (RemoteException ex) {
3149 }
3150 }
3151 }
3152
3153 private final class AppDirObserver extends FileObserver {
3154 public AppDirObserver(String path, int mask, boolean isrom) {
3155 super(path, mask);
3156 mRootDir = path;
3157 mIsRom = isrom;
3158 }
3159
3160 public void onEvent(int event, String path) {
3161 String removedPackage = null;
3162 int removedUid = -1;
3163 String addedPackage = null;
3164 int addedUid = -1;
3165
3166 synchronized (mInstallLock) {
3167 String fullPathStr = null;
3168 File fullPath = null;
3169 if (path != null) {
3170 fullPath = new File(mRootDir, path);
3171 fullPathStr = fullPath.getPath();
3172 }
3173
3174 if (Config.LOGV) Log.v(
3175 TAG, "File " + fullPathStr + " changed: "
3176 + Integer.toHexString(event));
3177
3178 if (!isPackageFilename(path)) {
3179 if (Config.LOGV) Log.v(
3180 TAG, "Ignoring change of non-package file: " + fullPathStr);
3181 return;
3182 }
3183
3184 if ((event&REMOVE_EVENTS) != 0) {
3185 synchronized (mInstallLock) {
3186 PackageParser.Package p = mAppDirs.get(fullPathStr);
3187 if (p != null) {
3188 removePackageLI(p, true);
3189 removedPackage = p.applicationInfo.packageName;
3190 removedUid = p.applicationInfo.uid;
3191 }
3192 }
3193 }
3194
3195 if ((event&ADD_EVENTS) != 0) {
3196 PackageParser.Package p = mAppDirs.get(fullPathStr);
3197 if (p == null) {
3198 p = scanPackageLI(fullPath, fullPath, fullPath,
3199 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3200 PackageParser.PARSE_CHATTY |
3201 PackageParser.PARSE_MUST_BE_APK,
3202 SCAN_MONITOR);
3203 if (p != null) {
3204 synchronized (mPackages) {
3205 grantPermissionsLP(p, false);
3206 }
3207 addedPackage = p.applicationInfo.packageName;
3208 addedUid = p.applicationInfo.uid;
3209 }
3210 }
3211 }
3212
3213 synchronized (mPackages) {
3214 mSettings.writeLP();
3215 }
3216 }
3217
3218 if (removedPackage != null) {
3219 Bundle extras = new Bundle(1);
3220 extras.putInt(Intent.EXTRA_UID, removedUid);
3221 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3222 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3223 }
3224 if (addedPackage != null) {
3225 Bundle extras = new Bundle(1);
3226 extras.putInt(Intent.EXTRA_UID, addedUid);
3227 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3228 }
3229 }
3230
3231 private final String mRootDir;
3232 private final boolean mIsRom;
3233 }
3234
3235 /* Called when a downloaded package installation has been confirmed by the user */
3236 public void installPackage(
3237 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
3238 mContext.enforceCallingOrSelfPermission(
3239 android.Manifest.permission.INSTALL_PACKAGES, null);
3240
3241 // Queue up an async operation since the package installation may take a little while.
3242 mHandler.post(new Runnable() {
3243 public void run() {
3244 mHandler.removeCallbacks(this);
3245 PackageInstalledInfo res;
3246 synchronized (mInstallLock) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003247 res = installPackageLI(packageURI, flags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
3249 if (observer != null) {
3250 try {
3251 observer.packageInstalled(res.name, res.returnCode);
3252 } catch (RemoteException e) {
3253 Log.i(TAG, "Observer no longer exists.");
3254 }
3255 }
3256 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3257 // call appears in the synchronized block above.
3258 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3259 res.removedInfo.sendBroadcast(false, true);
3260 Bundle extras = new Bundle(1);
3261 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003262 final boolean update = res.removedInfo.removedPackage != null;
3263 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3265 }
3266 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3267 res.pkg.applicationInfo.packageName,
3268 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003269 if (update) {
3270 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3271 res.pkg.applicationInfo.packageName,
3272 extras);
3273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 }
3275 Runtime.getRuntime().gc();
3276 }
3277 });
3278 }
3279
3280 class PackageInstalledInfo {
3281 String name;
3282 int uid;
3283 PackageParser.Package pkg;
3284 int returnCode;
3285 PackageRemovedInfo removedInfo;
3286 }
3287
3288 /*
3289 * Install a non-existing package.
3290 */
3291 private void installNewPackageLI(String pkgName,
3292 File tmpPackageFile,
3293 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003294 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 PackageInstalledInfo res) {
3296 // Remember this for later, in case we need to rollback this install
3297 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3298 res.name = pkgName;
3299 synchronized(mPackages) {
3300 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3301 // Don't allow installation over an existing package with the same name.
3302 Log.w(TAG, "Attempt to re-install " + pkgName
3303 + " without first uninstalling.");
3304 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3305 return;
3306 }
3307 }
3308 if (destPackageFile.exists()) {
3309 // It's safe to do this because we know (from the above check) that the file
3310 // isn't currently used for an installed package.
3311 destPackageFile.delete();
3312 }
3313 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3314 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3315 destResourceFile, pkg, 0,
3316 SCAN_MONITOR | SCAN_FORCE_DEX
3317 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003318 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3319 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 if (newPackage == null) {
3321 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3322 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3323 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3324 }
3325 } else {
3326 updateSettingsLI(pkgName, tmpPackageFile,
3327 destFilePath, destPackageFile,
3328 destResourceFile, pkg,
3329 newPackage,
3330 true,
3331 forwardLocked,
3332 res);
3333 // delete the partially installed application. the data directory will have to be
3334 // restored if it was already existing
3335 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3336 // remove package from internal structures. Note that we want deletePackageX to
3337 // delete the package data and cache directories that it created in
3338 // scanPackageLocked, unless those directories existed before we even tried to
3339 // install.
3340 deletePackageLI(
3341 pkgName, true,
3342 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3343 res.removedInfo);
3344 }
3345 }
3346 }
3347
3348 private void replacePackageLI(String pkgName,
3349 File tmpPackageFile,
3350 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003351 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 PackageInstalledInfo res) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003353 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 // First find the old package info and check signatures
3355 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003356 oldPackage = mPackages.get(pkgName);
3357 if(checkSignaturesLP(pkg, oldPackage) != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3359 return;
3360 }
3361 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003362 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003364 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003366 destPackageFile, destResourceFile, pkg, forwardLocked,
3367 newInstall, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003369 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003370 destPackageFile, destResourceFile, pkg, forwardLocked,
3371 newInstall, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 }
3373 }
3374
3375 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3376 File tmpPackageFile,
3377 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003378 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 PackageInstalledInfo res) {
3380 PackageParser.Package newPackage = null;
3381 String pkgName = deletedPackage.packageName;
3382 boolean deletedPkg = true;
3383 boolean updatedSettings = false;
3384 int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
3385 // First delete the existing package while retaining the data directory
3386 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3387 res.removedInfo)) {
3388 // If the existing package was'nt successfully deleted
3389 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3390 deletedPkg = false;
3391 } else {
3392 // Successfully deleted the old package. Now proceed with re-installation
3393 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3394 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3395 destResourceFile, pkg, parseFlags,
3396 SCAN_MONITOR | SCAN_FORCE_DEX
3397 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003398 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3399 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 if (newPackage == null) {
3401 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3402 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3403 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3404 }
3405 } else {
3406 updateSettingsLI(pkgName, tmpPackageFile,
3407 destFilePath, destPackageFile,
3408 destResourceFile, pkg,
3409 newPackage,
3410 true,
3411 forwardLocked,
3412 res);
3413 updatedSettings = true;
3414 }
3415 }
3416
3417 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3418 // If we deleted an exisiting package, the old source and resource files that we
3419 // were keeping around in case we needed them (see below) can now be deleted
3420 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3421 final ApplicationInfo installedPackageAppInfo =
3422 newPackage.applicationInfo;
3423 if (!deletedPackageAppInfo.sourceDir
3424 .equals(installedPackageAppInfo.sourceDir)) {
3425 new File(deletedPackageAppInfo.sourceDir).delete();
3426 }
3427 if (!deletedPackageAppInfo.publicSourceDir
3428 .equals(installedPackageAppInfo.publicSourceDir)) {
3429 new File(deletedPackageAppInfo.publicSourceDir).delete();
3430 }
3431 //update signature on the new package setting
3432 //this should always succeed, since we checked the
3433 //signature earlier.
3434 synchronized(mPackages) {
3435 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3436 parseFlags, true);
3437 }
3438 } else {
3439 // remove package from internal structures. Note that we want deletePackageX to
3440 // delete the package data and cache directories that it created in
3441 // scanPackageLocked, unless those directories existed before we even tried to
3442 // install.
3443 if(updatedSettings) {
3444 deletePackageLI(
3445 pkgName, true,
3446 PackageManager.DONT_DELETE_DATA,
3447 res.removedInfo);
3448 }
3449 // Since we failed to install the new package we need to restore the old
3450 // package that we deleted.
3451 if(deletedPkg) {
3452 installPackageLI(
3453 Uri.fromFile(new File(deletedPackage.mPath)),
3454 isForwardLocked(deletedPackage)
3455 ? PackageManager.FORWARD_LOCK_PACKAGE
The Android Open Source Project10592532009-03-18 17:39:46 -07003456 : 0, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 }
3458 }
3459 }
3460
3461 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3462 File tmpPackageFile,
3463 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003464 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 PackageInstalledInfo res) {
3466 PackageParser.Package newPackage = null;
3467 boolean updatedSettings = false;
3468 int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
3469 PackageParser.PARSE_IS_SYSTEM;
3470 String packageName = deletedPackage.packageName;
3471 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3472 if (packageName == null) {
3473 Log.w(TAG, "Attempt to delete null packageName.");
3474 return;
3475 }
3476 PackageParser.Package oldPkg;
3477 PackageSetting oldPkgSetting;
3478 synchronized (mPackages) {
3479 oldPkg = mPackages.get(packageName);
3480 oldPkgSetting = mSettings.mPackages.get(packageName);
3481 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3482 (oldPkgSetting == null)) {
3483 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3484 return;
3485 }
3486 }
3487 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3488 res.removedInfo.removedPackage = packageName;
3489 // Remove existing system package
3490 removePackageLI(oldPkg, true);
3491 synchronized (mPackages) {
3492 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3493 }
3494
3495 // Successfully disabled the old package. Now proceed with re-installation
3496 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3497 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3498 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3499 destResourceFile, pkg, parseFlags,
3500 SCAN_MONITOR | SCAN_FORCE_DEX
3501 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003502 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3503 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 if (newPackage == null) {
3505 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3506 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3507 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3508 }
3509 } else {
3510 updateSettingsLI(packageName, tmpPackageFile,
3511 destFilePath, destPackageFile,
3512 destResourceFile, pkg,
3513 newPackage,
3514 true,
3515 forwardLocked,
3516 res);
3517 updatedSettings = true;
3518 }
3519
3520 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3521 //update signature on the new package setting
3522 //this should always succeed, since we checked the
3523 //signature earlier.
3524 synchronized(mPackages) {
3525 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3526 parseFlags, true);
3527 }
3528 } else {
3529 // Re installation failed. Restore old information
3530 // Remove new pkg information
3531 removePackageLI(newPackage, true);
3532 // Add back the old system package
3533 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3534 oldPkgSetting.resourcePath,
3535 oldPkg, parseFlags,
3536 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003537 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 // Restore the old system information in Settings
3539 synchronized(mPackages) {
3540 if(updatedSettings) {
3541 mSettings.enableSystemPackageLP(packageName);
3542 }
3543 mSettings.writeLP();
3544 }
3545 }
3546 }
3547
3548 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3549 String destFilePath, File destPackageFile,
3550 File destResourceFile,
3551 PackageParser.Package pkg,
3552 PackageParser.Package newPackage,
3553 boolean replacingExistingPackage,
3554 boolean forwardLocked,
3555 PackageInstalledInfo res) {
3556 synchronized (mPackages) {
3557 //write settings. the installStatus will be incomplete at this stage.
3558 //note that the new package setting would have already been
3559 //added to mPackages. It hasn't been persisted yet.
3560 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3561 mSettings.writeLP();
3562 }
3563
3564 int retCode = 0;
3565 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3566 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3567 destPackageFile.toString());
3568 if (retCode != 0) {
3569 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3570 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3571 return;
3572 }
3573 }
3574 // XXX There are probably some big issues here: upon doing
3575 // the rename, we have reached the point of no return (the
3576 // original .apk is gone!), so we can't fail. Yet... we can.
3577 if (!tmpPackageFile.renameTo(destPackageFile)) {
3578 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3579 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3580 } else {
3581 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
3582 destResourceFile,
3583 forwardLocked);
3584 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3585 return;
3586 } else {
3587 Log.d(TAG, "New package installed in " + destPackageFile);
3588 }
3589 }
3590 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3591 if (mInstaller != null) {
3592 mInstaller.rmdex(tmpPackageFile.getPath());
3593 }
3594 }
3595
3596 synchronized (mPackages) {
3597 grantPermissionsLP(newPackage, true);
3598 res.name = pkgName;
3599 res.uid = newPackage.applicationInfo.uid;
3600 res.pkg = newPackage;
3601 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
3602 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3603 //to update install status
3604 mSettings.writeLP();
3605 }
3606 }
3607
The Android Open Source Project10592532009-03-18 17:39:46 -07003608 private PackageInstalledInfo installPackageLI(Uri pPackageURI,
3609 int pFlags, boolean newInstall) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 File tmpPackageFile = null;
3611 String pkgName = null;
3612 boolean forwardLocked = false;
3613 boolean replacingExistingPackage = false;
3614 // Result object to be returned
3615 PackageInstalledInfo res = new PackageInstalledInfo();
3616 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3617 res.uid = -1;
3618 res.pkg = null;
3619 res.removedInfo = new PackageRemovedInfo();
3620
3621 main_flow: try {
3622 tmpPackageFile = createTempPackageFile();
3623 if (tmpPackageFile == null) {
3624 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3625 break main_flow;
3626 }
3627 tmpPackageFile.deleteOnExit(); // paranoia
3628 if (pPackageURI.getScheme().equals("file")) {
3629 final File srcPackageFile = new File(pPackageURI.getPath());
3630 // We copy the source package file to a temp file and then rename it to the
3631 // destination file in order to eliminate a window where the package directory
3632 // scanner notices the new package file but it's not completely copied yet.
3633 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3634 Log.e(TAG, "Couldn't copy package file to temp file.");
3635 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3636 break main_flow;
3637 }
3638 } else if (pPackageURI.getScheme().equals("content")) {
3639 ParcelFileDescriptor fd;
3640 try {
3641 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
3642 } catch (FileNotFoundException e) {
3643 Log.e(TAG, "Couldn't open file descriptor from download service.");
3644 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3645 break main_flow;
3646 }
3647 if (fd == null) {
3648 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3649 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3650 break main_flow;
3651 }
3652 if (Config.LOGV) {
3653 Log.v(TAG, "Opened file descriptor from download service.");
3654 }
3655 ParcelFileDescriptor.AutoCloseInputStream
3656 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3657 // We copy the source package file to a temp file and then rename it to the
3658 // destination file in order to eliminate a window where the package directory
3659 // scanner notices the new package file but it's not completely copied yet.
3660 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3661 Log.e(TAG, "Couldn't copy package stream to temp file.");
3662 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3663 break main_flow;
3664 }
3665 } else {
3666 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
3667 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3668 break main_flow;
3669 }
3670 pkgName = PackageParser.parsePackageName(
3671 tmpPackageFile.getAbsolutePath(), 0);
3672 if (pkgName == null) {
3673 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3674 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3675 break main_flow;
3676 }
3677 res.name = pkgName;
3678 //initialize some variables before installing pkg
3679 final String pkgFileName = pkgName + ".apk";
3680 final File destDir = ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
3681 ? mDrmAppPrivateInstallDir
3682 : mAppInstallDir;
3683 final File destPackageFile = new File(destDir, pkgFileName);
3684 final String destFilePath = destPackageFile.getAbsolutePath();
3685 File destResourceFile;
3686 if ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
3687 final String publicZipFileName = pkgName + ".zip";
3688 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3689 forwardLocked = true;
3690 } else {
3691 destResourceFile = destPackageFile;
3692 }
3693 // Retrieve PackageSettings and parse package
3694 int parseFlags = PackageParser.PARSE_CHATTY;
3695 parseFlags |= mDefParseFlags;
3696 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3697 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07003698 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3700 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3701 if (pkg == null) {
3702 res.returnCode = pp.getParseError();
3703 break main_flow;
3704 }
3705 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3706 res.returnCode = pp.getParseError();
3707 break main_flow;
3708 }
3709
3710 synchronized (mPackages) {
3711 //check if installing already existing package
3712 if ((pFlags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
3713 && mPackages.containsKey(pkgName)) {
3714 replacingExistingPackage = true;
3715 }
3716 }
3717
3718 if(replacingExistingPackage) {
3719 replacePackageLI(pkgName,
3720 tmpPackageFile,
3721 destFilePath, destPackageFile, destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003722 pkg, forwardLocked, newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 res);
3724 } else {
3725 installNewPackageLI(pkgName,
3726 tmpPackageFile,
3727 destFilePath, destPackageFile, destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003728 pkg, forwardLocked, newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 res);
3730 }
3731 } finally {
3732 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3733 tmpPackageFile.delete();
3734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003736 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 }
3738
3739 private int setPermissionsLI(String pkgName,
3740 PackageParser.Package newPackage,
3741 String destFilePath,
3742 File destResourceFile,
3743 boolean forwardLocked) {
3744 int retCode;
3745 if (forwardLocked) {
3746 try {
3747 extractPublicFiles(newPackage, destResourceFile);
3748 } catch (IOException e) {
3749 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3750 " forward-locked app.");
3751 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3752 } finally {
3753 //TODO clean up the extracted public files
3754 }
3755 if (mInstaller != null) {
3756 retCode = mInstaller.setForwardLockPerm(pkgName,
3757 newPackage.applicationInfo.uid);
3758 } else {
3759 final int filePermissions =
3760 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3761 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3762 newPackage.applicationInfo.uid);
3763 }
3764 } else {
3765 final int filePermissions =
3766 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3767 |FileUtils.S_IROTH;
3768 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3769 }
3770 if (retCode != 0) {
3771 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3772 + ". The return code was: " + retCode);
3773 }
3774 return PackageManager.INSTALL_SUCCEEDED;
3775 }
3776
3777 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3778 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3779 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3780 }
3781
3782 private void extractPublicFiles(PackageParser.Package newPackage,
3783 File publicZipFile) throws IOException {
3784 final ZipOutputStream publicZipOutStream =
3785 new ZipOutputStream(new FileOutputStream(publicZipFile));
3786 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3787
3788 // Copy manifest, resources.arsc and res directory to public zip
3789
3790 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3791 while (privateZipEntries.hasMoreElements()) {
3792 final ZipEntry zipEntry = privateZipEntries.nextElement();
3793 final String zipEntryName = zipEntry.getName();
3794 if ("AndroidManifest.xml".equals(zipEntryName)
3795 || "resources.arsc".equals(zipEntryName)
3796 || zipEntryName.startsWith("res/")) {
3797 try {
3798 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3799 } catch (IOException e) {
3800 try {
3801 publicZipOutStream.close();
3802 throw e;
3803 } finally {
3804 publicZipFile.delete();
3805 }
3806 }
3807 }
3808 }
3809
3810 publicZipOutStream.close();
3811 FileUtils.setPermissions(
3812 publicZipFile.getAbsolutePath(),
3813 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
3814 -1, -1);
3815 }
3816
3817 private static void copyZipEntry(ZipEntry zipEntry,
3818 ZipFile inZipFile,
3819 ZipOutputStream outZipStream) throws IOException {
3820 byte[] buffer = new byte[4096];
3821 int num;
3822
3823 ZipEntry newEntry;
3824 if (zipEntry.getMethod() == ZipEntry.STORED) {
3825 // Preserve the STORED method of the input entry.
3826 newEntry = new ZipEntry(zipEntry);
3827 } else {
3828 // Create a new entry so that the compressed len is recomputed.
3829 newEntry = new ZipEntry(zipEntry.getName());
3830 }
3831 outZipStream.putNextEntry(newEntry);
3832
3833 InputStream data = inZipFile.getInputStream(zipEntry);
3834 while ((num = data.read(buffer)) > 0) {
3835 outZipStream.write(buffer, 0, num);
3836 }
3837 outZipStream.flush();
3838 }
3839
3840 private void deleteTempPackageFiles() {
3841 FilenameFilter filter = new FilenameFilter() {
3842 public boolean accept(File dir, String name) {
3843 return name.startsWith("vmdl") && name.endsWith(".tmp");
3844 }
3845 };
3846 String tmpFilesList[] = mAppInstallDir.list(filter);
3847 if(tmpFilesList == null) {
3848 return;
3849 }
3850 for(int i = 0; i < tmpFilesList.length; i++) {
3851 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
3852 tmpFile.delete();
3853 }
3854 }
3855
3856 private File createTempPackageFile() {
3857 File tmpPackageFile;
3858 try {
3859 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
3860 } catch (IOException e) {
3861 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
3862 return null;
3863 }
3864 try {
3865 FileUtils.setPermissions(
3866 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
3867 -1, -1);
3868 } catch (IOException e) {
3869 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
3870 return null;
3871 }
3872 return tmpPackageFile;
3873 }
3874
3875 public void deletePackage(final String packageName,
3876 final IPackageDeleteObserver observer,
3877 final int flags) {
3878 mContext.enforceCallingOrSelfPermission(
3879 android.Manifest.permission.DELETE_PACKAGES, null);
3880 // Queue up an async operation since the package deletion may take a little while.
3881 mHandler.post(new Runnable() {
3882 public void run() {
3883 mHandler.removeCallbacks(this);
3884 final boolean succeded = deletePackageX(packageName, true, true, flags);
3885 if (observer != null) {
3886 try {
3887 observer.packageDeleted(succeded);
3888 } catch (RemoteException e) {
3889 Log.i(TAG, "Observer no longer exists.");
3890 } //end catch
3891 } //end if
3892 } //end run
3893 });
3894 }
3895
3896 /**
3897 * This method is an internal method that could be get invoked either
3898 * to delete an installed package or to clean up a failed installation.
3899 * After deleting an installed package, a broadcast is sent to notify any
3900 * listeners that the package has been installed. For cleaning up a failed
3901 * installation, the broadcast is not necessary since the package's
3902 * installation wouldn't have sent the initial broadcast either
3903 * The key steps in deleting a package are
3904 * deleting the package information in internal structures like mPackages,
3905 * deleting the packages base directories through installd
3906 * updating mSettings to reflect current status
3907 * persisting settings for later use
3908 * sending a broadcast if necessary
3909 */
3910
3911 private boolean deletePackageX(String packageName, boolean sendBroadCast,
3912 boolean deleteCodeAndResources, int flags) {
3913 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07003914 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003915
3916 synchronized (mInstallLock) {
3917 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
3918 }
3919
3920 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07003921 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
3922 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
3923
3924 // If the removed package was a system update, the old system packaged
3925 // was re-enabled; we need to broadcast this information
3926 if (systemUpdate) {
3927 Bundle extras = new Bundle(1);
3928 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
3929 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3930
3931 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
3932 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
3933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 }
3935 return res;
3936 }
3937
3938 static class PackageRemovedInfo {
3939 String removedPackage;
3940 int uid = -1;
3941 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07003942 boolean isRemovedPackageSystemUpdate = false;
3943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 void sendBroadcast(boolean fullRemove, boolean replacing) {
3945 Bundle extras = new Bundle(1);
3946 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
3947 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
3948 if (replacing) {
3949 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3950 }
3951 if (removedPackage != null) {
3952 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3953 }
3954 if (removedUid >= 0) {
3955 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
3956 }
3957 }
3958 }
3959
3960 /*
3961 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
3962 * flag is not set, the data directory is removed as well.
3963 * make sure this flag is set for partially installed apps. If not its meaningless to
3964 * delete a partially installed application.
3965 */
3966 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
3967 int flags) {
3968 String packageName = p.packageName;
3969 outInfo.removedPackage = packageName;
3970 removePackageLI(p, true);
3971 // Retrieve object to delete permissions for shared user later on
3972 PackageSetting deletedPs;
3973 synchronized (mPackages) {
3974 deletedPs = mSettings.mPackages.get(packageName);
3975 }
3976 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
3977 if (mInstaller != null) {
3978 int retCode = mInstaller.remove(packageName);
3979 if (retCode < 0) {
3980 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
3981 + packageName + ", retcode=" + retCode);
3982 // we don't consider this to be a failure of the core package deletion
3983 }
3984 } else {
3985 //for emulator
3986 PackageParser.Package pkg = mPackages.get(packageName);
3987 File dataDir = new File(pkg.applicationInfo.dataDir);
3988 dataDir.delete();
3989 }
3990 synchronized (mPackages) {
3991 outInfo.removedUid = mSettings.removePackageLP(packageName);
3992 }
3993 }
3994 synchronized (mPackages) {
3995 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
3996 // remove permissions associated with package
3997 mSettings.updateSharedUserPerms (deletedPs);
3998 }
3999 // Save settings now
4000 mSettings.writeLP ();
4001 }
4002 }
4003
4004 /*
4005 * Tries to delete system package.
4006 */
4007 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004008 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 ApplicationInfo applicationInfo = p.applicationInfo;
4010 //applicable for non-partially installed applications only
4011 if (applicationInfo == null) {
4012 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4013 return false;
4014 }
4015 PackageSetting ps = null;
4016 // Confirm if the system package has been updated
4017 // An updated system app can be deleted. This will also have to restore
4018 // the system pkg from system partition
4019 synchronized (mPackages) {
4020 ps = mSettings.getDisabledSystemPkg(p.packageName);
4021 }
4022 if (ps == null) {
4023 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4024 return false;
4025 } else {
4026 Log.i(TAG, "Deleting system pkg from data partition");
4027 }
4028 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004029 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004030 boolean deleteCodeAndResources = false;
4031 if (ps.versionCode < p.mVersionCode) {
4032 // Delete code and resources for downgrades
4033 deleteCodeAndResources = true;
4034 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4035 flags &= ~PackageManager.DONT_DELETE_DATA;
4036 }
4037 } else {
4038 // Preserve data by setting flag
4039 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4040 flags |= PackageManager.DONT_DELETE_DATA;
4041 }
4042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4044 if (!ret) {
4045 return false;
4046 }
4047 synchronized (mPackages) {
4048 // Reinstate the old system package
4049 mSettings.enableSystemPackageLP(p.packageName);
4050 }
4051 // Install the system package
4052 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4053 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4054 SCAN_MONITOR);
4055
4056 if (newPkg == null) {
4057 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4058 return false;
4059 }
4060 synchronized (mPackages) {
4061 mSettings.writeLP();
4062 }
4063 return true;
4064 }
4065
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004066 private void deletePackageResourcesLI(String packageName,
4067 String sourceDir, String publicSourceDir) {
4068 File sourceFile = new File(sourceDir);
4069 if (!sourceFile.exists()) {
4070 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4071 }
4072 // Delete application's code and resources
4073 sourceFile.delete();
4074 final File publicSourceFile = new File(publicSourceDir);
4075 if (publicSourceFile.exists()) {
4076 publicSourceFile.delete();
4077 }
4078 if (mInstaller != null) {
4079 int retCode = mInstaller.rmdex(sourceFile.toString());
4080 if (retCode < 0) {
4081 Log.w(TAG, "Couldn't remove dex file for package: "
4082 + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4083 // we don't consider this to be a failure of the core package deletion
4084 }
4085 }
4086 }
4087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4089 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4090 ApplicationInfo applicationInfo = p.applicationInfo;
4091 if (applicationInfo == null) {
4092 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4093 return false;
4094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 outInfo.uid = applicationInfo.uid;
4096
4097 // Delete package data from internal structures and also remove data if flag is set
4098 removePackageDataLI(p, outInfo, flags);
4099
4100 // Delete application code and resources
4101 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004102 deletePackageResourcesLI(applicationInfo.packageName,
4103 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 }
4105 return true;
4106 }
4107
4108 /*
4109 * This method handles package deletion in general
4110 */
4111 private boolean deletePackageLI(String packageName,
4112 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4113 if (packageName == null) {
4114 Log.w(TAG, "Attempt to delete null packageName.");
4115 return false;
4116 }
4117 PackageParser.Package p;
4118 boolean dataOnly = false;
4119 synchronized (mPackages) {
4120 p = mPackages.get(packageName);
4121 if (p == null) {
4122 //this retrieves partially installed apps
4123 dataOnly = true;
4124 PackageSetting ps = mSettings.mPackages.get(packageName);
4125 if (ps == null) {
4126 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4127 return false;
4128 }
4129 p = ps.pkg;
4130 }
4131 }
4132 if (p == null) {
4133 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4134 return false;
4135 }
4136
4137 if (dataOnly) {
4138 // Delete application data first
4139 removePackageDataLI(p, outInfo, flags);
4140 return true;
4141 }
4142 // At this point the package should have ApplicationInfo associated with it
4143 if (p.applicationInfo == null) {
4144 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4145 return false;
4146 }
4147 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4148 Log.i(TAG, "Removing system package:"+p.packageName);
4149 // When an updated system application is deleted we delete the existing resources as well and
4150 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004151 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 }
4153 Log.i(TAG, "Removing non-system package:"+p.packageName);
4154 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4155 }
4156
4157 public void clearApplicationUserData(final String packageName,
4158 final IPackageDataObserver observer) {
4159 mContext.enforceCallingOrSelfPermission(
4160 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4161 // Queue up an async operation since the package deletion may take a little while.
4162 mHandler.post(new Runnable() {
4163 public void run() {
4164 mHandler.removeCallbacks(this);
4165 final boolean succeeded;
4166 synchronized (mInstallLock) {
4167 succeeded = clearApplicationUserDataLI(packageName);
4168 }
4169 if (succeeded) {
4170 // invoke DeviceStorageMonitor's update method to clear any notifications
4171 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4172 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4173 if (dsm != null) {
4174 dsm.updateMemory();
4175 }
4176 }
4177 if(observer != null) {
4178 try {
4179 observer.onRemoveCompleted(packageName, succeeded);
4180 } catch (RemoteException e) {
4181 Log.i(TAG, "Observer no longer exists.");
4182 }
4183 } //end if observer
4184 } //end run
4185 });
4186 }
4187
4188 private boolean clearApplicationUserDataLI(String packageName) {
4189 if (packageName == null) {
4190 Log.w(TAG, "Attempt to delete null packageName.");
4191 return false;
4192 }
4193 PackageParser.Package p;
4194 boolean dataOnly = false;
4195 synchronized (mPackages) {
4196 p = mPackages.get(packageName);
4197 if(p == null) {
4198 dataOnly = true;
4199 PackageSetting ps = mSettings.mPackages.get(packageName);
4200 if((ps == null) || (ps.pkg == null)) {
4201 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4202 return false;
4203 }
4204 p = ps.pkg;
4205 }
4206 }
4207 if(!dataOnly) {
4208 //need to check this only for fully installed applications
4209 if (p == null) {
4210 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4211 return false;
4212 }
4213 final ApplicationInfo applicationInfo = p.applicationInfo;
4214 if (applicationInfo == null) {
4215 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4216 return false;
4217 }
4218 }
4219 if (mInstaller != null) {
4220 int retCode = mInstaller.clearUserData(packageName);
4221 if (retCode < 0) {
4222 Log.w(TAG, "Couldn't remove cache files for package: "
4223 + packageName);
4224 return false;
4225 }
4226 }
4227 return true;
4228 }
4229
4230 public void deleteApplicationCacheFiles(final String packageName,
4231 final IPackageDataObserver observer) {
4232 mContext.enforceCallingOrSelfPermission(
4233 android.Manifest.permission.DELETE_CACHE_FILES, null);
4234 // Queue up an async operation since the package deletion may take a little while.
4235 mHandler.post(new Runnable() {
4236 public void run() {
4237 mHandler.removeCallbacks(this);
4238 final boolean succeded;
4239 synchronized (mInstallLock) {
4240 succeded = deleteApplicationCacheFilesLI(packageName);
4241 }
4242 if(observer != null) {
4243 try {
4244 observer.onRemoveCompleted(packageName, succeded);
4245 } catch (RemoteException e) {
4246 Log.i(TAG, "Observer no longer exists.");
4247 }
4248 } //end if observer
4249 } //end run
4250 });
4251 }
4252
4253 private boolean deleteApplicationCacheFilesLI(String packageName) {
4254 if (packageName == null) {
4255 Log.w(TAG, "Attempt to delete null packageName.");
4256 return false;
4257 }
4258 PackageParser.Package p;
4259 synchronized (mPackages) {
4260 p = mPackages.get(packageName);
4261 }
4262 if (p == null) {
4263 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4264 return false;
4265 }
4266 final ApplicationInfo applicationInfo = p.applicationInfo;
4267 if (applicationInfo == null) {
4268 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4269 return false;
4270 }
4271 if (mInstaller != null) {
4272 int retCode = mInstaller.deleteCacheFiles(packageName);
4273 if (retCode < 0) {
4274 Log.w(TAG, "Couldn't remove cache files for package: "
4275 + packageName);
4276 return false;
4277 }
4278 }
4279 return true;
4280 }
4281
4282 public void getPackageSizeInfo(final String packageName,
4283 final IPackageStatsObserver observer) {
4284 mContext.enforceCallingOrSelfPermission(
4285 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4286 // Queue up an async operation since the package deletion may take a little while.
4287 mHandler.post(new Runnable() {
4288 public void run() {
4289 mHandler.removeCallbacks(this);
4290 PackageStats lStats = new PackageStats(packageName);
4291 final boolean succeded;
4292 synchronized (mInstallLock) {
4293 succeded = getPackageSizeInfoLI(packageName, lStats);
4294 }
4295 if(observer != null) {
4296 try {
4297 observer.onGetStatsCompleted(lStats, succeded);
4298 } catch (RemoteException e) {
4299 Log.i(TAG, "Observer no longer exists.");
4300 }
4301 } //end if observer
4302 } //end run
4303 });
4304 }
4305
4306 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4307 if (packageName == null) {
4308 Log.w(TAG, "Attempt to get size of null packageName.");
4309 return false;
4310 }
4311 PackageParser.Package p;
4312 boolean dataOnly = false;
4313 synchronized (mPackages) {
4314 p = mPackages.get(packageName);
4315 if(p == null) {
4316 dataOnly = true;
4317 PackageSetting ps = mSettings.mPackages.get(packageName);
4318 if((ps == null) || (ps.pkg == null)) {
4319 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4320 return false;
4321 }
4322 p = ps.pkg;
4323 }
4324 }
4325 String publicSrcDir = null;
4326 if(!dataOnly) {
4327 final ApplicationInfo applicationInfo = p.applicationInfo;
4328 if (applicationInfo == null) {
4329 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4330 return false;
4331 }
4332 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4333 }
4334 if (mInstaller != null) {
4335 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4336 publicSrcDir, pStats);
4337 if (res < 0) {
4338 return false;
4339 } else {
4340 return true;
4341 }
4342 }
4343 return true;
4344 }
4345
4346
4347 public void addPackageToPreferred(String packageName) {
4348 mContext.enforceCallingOrSelfPermission(
4349 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4350
4351 synchronized (mPackages) {
4352 PackageParser.Package p = mPackages.get(packageName);
4353 if (p == null) {
4354 return;
4355 }
4356 PackageSetting ps = (PackageSetting)p.mExtras;
4357 if (ps != null) {
4358 mSettings.mPreferredPackages.remove(ps);
4359 mSettings.mPreferredPackages.add(0, ps);
4360 updatePreferredIndicesLP();
4361 mSettings.writeLP();
4362 }
4363 }
4364 }
4365
4366 public void removePackageFromPreferred(String packageName) {
4367 mContext.enforceCallingOrSelfPermission(
4368 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4369
4370 synchronized (mPackages) {
4371 PackageParser.Package p = mPackages.get(packageName);
4372 if (p == null) {
4373 return;
4374 }
4375 if (p.mPreferredOrder > 0) {
4376 PackageSetting ps = (PackageSetting)p.mExtras;
4377 if (ps != null) {
4378 mSettings.mPreferredPackages.remove(ps);
4379 p.mPreferredOrder = 0;
4380 updatePreferredIndicesLP();
4381 mSettings.writeLP();
4382 }
4383 }
4384 }
4385 }
4386
4387 private void updatePreferredIndicesLP() {
4388 final ArrayList<PackageSetting> pkgs
4389 = mSettings.mPreferredPackages;
4390 final int N = pkgs.size();
4391 for (int i=0; i<N; i++) {
4392 pkgs.get(i).pkg.mPreferredOrder = N - i;
4393 }
4394 }
4395
4396 public List<PackageInfo> getPreferredPackages(int flags) {
4397 synchronized (mPackages) {
4398 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4399 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4400 final int N = pref.size();
4401 for (int i=0; i<N; i++) {
4402 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4403 }
4404 return res;
4405 }
4406 }
4407
4408 public void addPreferredActivity(IntentFilter filter, int match,
4409 ComponentName[] set, ComponentName activity) {
4410 mContext.enforceCallingOrSelfPermission(
4411 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4412
4413 synchronized (mPackages) {
4414 Log.i(TAG, "Adding preferred activity " + activity + ":");
4415 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4416 mSettings.mPreferredActivities.addFilter(
4417 new PreferredActivity(filter, match, set, activity));
4418 mSettings.writeLP();
4419 }
4420 }
4421
4422 public void clearPackagePreferredActivities(String packageName) {
4423 mContext.enforceCallingOrSelfPermission(
4424 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4425
4426 synchronized (mPackages) {
4427 if (clearPackagePreferredActivitiesLP(packageName)) {
4428 mSettings.writeLP();
4429 }
4430 }
4431 }
4432
4433 boolean clearPackagePreferredActivitiesLP(String packageName) {
4434 boolean changed = false;
4435 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4436 while (it.hasNext()) {
4437 PreferredActivity pa = it.next();
4438 if (pa.mActivity.getPackageName().equals(packageName)) {
4439 it.remove();
4440 changed = true;
4441 }
4442 }
4443 return changed;
4444 }
4445
4446 public int getPreferredActivities(List<IntentFilter> outFilters,
4447 List<ComponentName> outActivities, String packageName) {
4448
4449 int num = 0;
4450 synchronized (mPackages) {
4451 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4452 while (it.hasNext()) {
4453 PreferredActivity pa = it.next();
4454 if (packageName == null
4455 || pa.mActivity.getPackageName().equals(packageName)) {
4456 if (outFilters != null) {
4457 outFilters.add(new IntentFilter(pa));
4458 }
4459 if (outActivities != null) {
4460 outActivities.add(pa.mActivity);
4461 }
4462 }
4463 }
4464 }
4465
4466 return num;
4467 }
4468
4469 public void setApplicationEnabledSetting(String appPackageName,
4470 int newState, int flags) {
4471 setEnabledSetting(appPackageName, null, newState, flags);
4472 }
4473
4474 public void setComponentEnabledSetting(ComponentName componentName,
4475 int newState, int flags) {
4476 setEnabledSetting(componentName.getPackageName(),
4477 componentName.getClassName(), newState, flags);
4478 }
4479
4480 private void setEnabledSetting(
4481 final String packageNameStr, String classNameStr, int newState, final int flags) {
4482 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4483 || newState == COMPONENT_ENABLED_STATE_ENABLED
4484 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4485 throw new IllegalArgumentException("Invalid new component state: "
4486 + newState);
4487 }
4488 PackageSetting pkgSetting;
4489 final int uid = Binder.getCallingUid();
4490 final int permission = mContext.checkCallingPermission(
4491 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4492 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4493 int packageUid = -1;
4494 synchronized (mPackages) {
4495 pkgSetting = mSettings.mPackages.get(packageNameStr);
4496 if (pkgSetting == null) {
4497 if (classNameStr == null) {
4498 throw new IllegalArgumentException(
4499 "Unknown package: " + packageNameStr);
4500 }
4501 throw new IllegalArgumentException(
4502 "Unknown component: " + packageNameStr
4503 + "/" + classNameStr);
4504 }
4505 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4506 throw new SecurityException(
4507 "Permission Denial: attempt to change component state from pid="
4508 + Binder.getCallingPid()
4509 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4510 }
4511 packageUid = pkgSetting.userId;
4512 if (classNameStr == null) {
4513 // We're dealing with an application/package level state change
4514 pkgSetting.enabled = newState;
4515 } else {
4516 // We're dealing with a component level state change
4517 switch (newState) {
4518 case COMPONENT_ENABLED_STATE_ENABLED:
4519 pkgSetting.enableComponentLP(classNameStr);
4520 break;
4521 case COMPONENT_ENABLED_STATE_DISABLED:
4522 pkgSetting.disableComponentLP(classNameStr);
4523 break;
4524 case COMPONENT_ENABLED_STATE_DEFAULT:
4525 pkgSetting.restoreComponentLP(classNameStr);
4526 break;
4527 default:
4528 Log.e(TAG, "Invalid new component state: " + newState);
4529 }
4530 }
4531 mSettings.writeLP();
4532 }
4533
4534 long callingId = Binder.clearCallingIdentity();
4535 try {
4536 Bundle extras = new Bundle(2);
4537 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
4538 (flags&PackageManager.DONT_KILL_APP) != 0);
4539 extras.putInt(Intent.EXTRA_UID, packageUid);
4540 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
4541 } finally {
4542 Binder.restoreCallingIdentity(callingId);
4543 }
4544 }
4545
4546 public int getApplicationEnabledSetting(String appPackageName) {
4547 synchronized (mPackages) {
4548 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
4549 if (pkg == null) {
4550 throw new IllegalArgumentException("Unknown package: " + appPackageName);
4551 }
4552 return pkg.enabled;
4553 }
4554 }
4555
4556 public int getComponentEnabledSetting(ComponentName componentName) {
4557 synchronized (mPackages) {
4558 final String packageNameStr = componentName.getPackageName();
4559 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
4560 if (pkg == null) {
4561 throw new IllegalArgumentException("Unknown component: " + componentName);
4562 }
4563 final String classNameStr = componentName.getClassName();
4564 return pkg.currentEnabledStateLP(classNameStr);
4565 }
4566 }
4567
4568 public void enterSafeMode() {
4569 if (!mSystemReady) {
4570 mSafeMode = true;
4571 }
4572 }
4573
4574 public void systemReady() {
4575 mSystemReady = true;
4576 }
4577
4578 public boolean isSafeMode() {
4579 return mSafeMode;
4580 }
4581
4582 public boolean hasSystemUidErrors() {
4583 return mHasSystemUidErrors;
4584 }
4585
4586 static String arrayToString(int[] array) {
4587 StringBuffer buf = new StringBuffer(128);
4588 buf.append('[');
4589 if (array != null) {
4590 for (int i=0; i<array.length; i++) {
4591 if (i > 0) buf.append(", ");
4592 buf.append(array[i]);
4593 }
4594 }
4595 buf.append(']');
4596 return buf.toString();
4597 }
4598
4599 @Override
4600 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4601 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4602 != PackageManager.PERMISSION_GRANTED) {
4603 pw.println("Permission Denial: can't dump ActivityManager from from pid="
4604 + Binder.getCallingPid()
4605 + ", uid=" + Binder.getCallingUid()
4606 + " without permission "
4607 + android.Manifest.permission.DUMP);
4608 return;
4609 }
4610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 synchronized (mPackages) {
4612 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004613 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 pw.println(" ");
4615 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004616 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 pw.println(" ");
4618 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004619 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 pw.println(" ");
4621 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004622 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 pw.println(" ");
4624 pw.println("Preferred Packages:");
4625 {
4626 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004627 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 }
4629 }
4630 pw.println(" ");
4631 pw.println("Permissions:");
4632 {
4633 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004634 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
4635 pw.print(Integer.toHexString(System.identityHashCode(p)));
4636 pw.println("):");
4637 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
4638 pw.print(" uid="); pw.print(p.uid);
4639 pw.print(" gids="); pw.print(arrayToString(p.gids));
4640 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 }
4642 }
4643 pw.println(" ");
4644 pw.println("Packages:");
4645 {
4646 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004647 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
4648 pw.print(Integer.toHexString(System.identityHashCode(ps)));
4649 pw.println("):");
4650 pw.print(" userId="); pw.print(ps.userId);
4651 pw.print(" gids="); pw.println(arrayToString(ps.gids));
4652 pw.print(" sharedUser="); pw.println(ps.sharedUser);
4653 pw.print(" pkg="); pw.println(ps.pkg);
4654 pw.print(" codePath="); pw.println(ps.codePathString);
4655 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004657 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004659 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
4660 pw.print(" signatures="); pw.println(ps.signatures);
4661 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
4662 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
4663 pw.print(" installStatus="); pw.print(ps.installStatus);
4664 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 if (ps.disabledComponents.size() > 0) {
4666 pw.println(" disabledComponents:");
4667 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004668 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 }
4670 }
4671 if (ps.enabledComponents.size() > 0) {
4672 pw.println(" enabledComponents:");
4673 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004674 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 }
4676 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004677 if (ps.grantedPermissions.size() > 0) {
4678 pw.println(" grantedPermissions:");
4679 for (String s : ps.grantedPermissions) {
4680 pw.print(" "); pw.println(s);
4681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004683 if (ps.loadedPermissions.size() > 0) {
4684 pw.println(" loadedPermissions:");
4685 for (String s : ps.loadedPermissions) {
4686 pw.print(" "); pw.println(s);
4687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 }
4689 }
4690 }
4691 pw.println(" ");
4692 pw.println("Shared Users:");
4693 {
4694 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004695 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
4696 pw.print(Integer.toHexString(System.identityHashCode(su)));
4697 pw.println("):");
4698 pw.print(" userId="); pw.print(su.userId);
4699 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 pw.println(" grantedPermissions:");
4701 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004702 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 }
4704 pw.println(" loadedPermissions:");
4705 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004706 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 }
4708 }
4709 }
4710 pw.println(" ");
4711 pw.println("Settings parse messages:");
4712 pw.println(mSettings.mReadMessages.toString());
4713 }
4714 }
4715
4716 static final class BasePermission {
4717 final static int TYPE_NORMAL = 0;
4718 final static int TYPE_BUILTIN = 1;
4719 final static int TYPE_DYNAMIC = 2;
4720
4721 final String name;
4722 final String sourcePackage;
4723 final int type;
4724 PackageParser.Permission perm;
4725 PermissionInfo pendingInfo;
4726 int uid;
4727 int[] gids;
4728
4729 BasePermission(String _name, String _sourcePackage, int _type) {
4730 name = _name;
4731 sourcePackage = _sourcePackage;
4732 type = _type;
4733 }
4734 }
4735
4736 static class PackageSignatures {
4737 private Signature[] mSignatures;
4738
4739 PackageSignatures(Signature[] sigs) {
4740 assignSignatures(sigs);
4741 }
4742
4743 PackageSignatures() {
4744 }
4745
4746 void writeXml(XmlSerializer serializer, String tagName,
4747 ArrayList<Signature> pastSignatures) throws IOException {
4748 if (mSignatures == null) {
4749 return;
4750 }
4751 serializer.startTag(null, tagName);
4752 serializer.attribute(null, "count",
4753 Integer.toString(mSignatures.length));
4754 for (int i=0; i<mSignatures.length; i++) {
4755 serializer.startTag(null, "cert");
4756 final Signature sig = mSignatures[i];
4757 final int sigHash = sig.hashCode();
4758 final int numPast = pastSignatures.size();
4759 int j;
4760 for (j=0; j<numPast; j++) {
4761 Signature pastSig = pastSignatures.get(j);
4762 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
4763 serializer.attribute(null, "index", Integer.toString(j));
4764 break;
4765 }
4766 }
4767 if (j >= numPast) {
4768 pastSignatures.add(sig);
4769 serializer.attribute(null, "index", Integer.toString(numPast));
4770 serializer.attribute(null, "key", sig.toCharsString());
4771 }
4772 serializer.endTag(null, "cert");
4773 }
4774 serializer.endTag(null, tagName);
4775 }
4776
4777 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
4778 throws IOException, XmlPullParserException {
4779 String countStr = parser.getAttributeValue(null, "count");
4780 if (countStr == null) {
4781 reportSettingsProblem(Log.WARN,
4782 "Error in package manager settings: <signatures> has"
4783 + " no count at " + parser.getPositionDescription());
4784 XmlUtils.skipCurrentTag(parser);
4785 }
4786 final int count = Integer.parseInt(countStr);
4787 mSignatures = new Signature[count];
4788 int pos = 0;
4789
4790 int outerDepth = parser.getDepth();
4791 int type;
4792 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4793 && (type != XmlPullParser.END_TAG
4794 || parser.getDepth() > outerDepth)) {
4795 if (type == XmlPullParser.END_TAG
4796 || type == XmlPullParser.TEXT) {
4797 continue;
4798 }
4799
4800 String tagName = parser.getName();
4801 if (tagName.equals("cert")) {
4802 if (pos < count) {
4803 String index = parser.getAttributeValue(null, "index");
4804 if (index != null) {
4805 try {
4806 int idx = Integer.parseInt(index);
4807 String key = parser.getAttributeValue(null, "key");
4808 if (key == null) {
4809 if (idx >= 0 && idx < pastSignatures.size()) {
4810 Signature sig = pastSignatures.get(idx);
4811 if (sig != null) {
4812 mSignatures[pos] = pastSignatures.get(idx);
4813 pos++;
4814 } else {
4815 reportSettingsProblem(Log.WARN,
4816 "Error in package manager settings: <cert> "
4817 + "index " + index + " is not defined at "
4818 + parser.getPositionDescription());
4819 }
4820 } else {
4821 reportSettingsProblem(Log.WARN,
4822 "Error in package manager settings: <cert> "
4823 + "index " + index + " is out of bounds at "
4824 + parser.getPositionDescription());
4825 }
4826 } else {
4827 while (pastSignatures.size() <= idx) {
4828 pastSignatures.add(null);
4829 }
4830 Signature sig = new Signature(key);
4831 pastSignatures.set(idx, sig);
4832 mSignatures[pos] = sig;
4833 pos++;
4834 }
4835 } catch (NumberFormatException e) {
4836 reportSettingsProblem(Log.WARN,
4837 "Error in package manager settings: <cert> "
4838 + "index " + index + " is not a number at "
4839 + parser.getPositionDescription());
4840 }
4841 } else {
4842 reportSettingsProblem(Log.WARN,
4843 "Error in package manager settings: <cert> has"
4844 + " no index at " + parser.getPositionDescription());
4845 }
4846 } else {
4847 reportSettingsProblem(Log.WARN,
4848 "Error in package manager settings: too "
4849 + "many <cert> tags, expected " + count
4850 + " at " + parser.getPositionDescription());
4851 }
4852 } else {
4853 reportSettingsProblem(Log.WARN,
4854 "Unknown element under <cert>: "
4855 + parser.getName());
4856 }
4857 XmlUtils.skipCurrentTag(parser);
4858 }
4859
4860 if (pos < count) {
4861 // Should never happen -- there is an error in the written
4862 // settings -- but if it does we don't want to generate
4863 // a bad array.
4864 Signature[] newSigs = new Signature[pos];
4865 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
4866 mSignatures = newSigs;
4867 }
4868 }
4869
4870 /**
4871 * If any of the given 'sigs' is contained in the existing signatures,
4872 * then completely replace the current signatures with the ones in
4873 * 'sigs'. This is used for updating an existing package to a newly
4874 * installed version.
4875 */
4876 boolean updateSignatures(Signature[] sigs, boolean update) {
4877 if (mSignatures == null) {
4878 if (update) {
4879 assignSignatures(sigs);
4880 }
4881 return true;
4882 }
4883 if (sigs == null) {
4884 return false;
4885 }
4886
4887 for (int i=0; i<sigs.length; i++) {
4888 Signature sig = sigs[i];
4889 for (int j=0; j<mSignatures.length; j++) {
4890 if (mSignatures[j].equals(sig)) {
4891 if (update) {
4892 assignSignatures(sigs);
4893 }
4894 return true;
4895 }
4896 }
4897 }
4898 return false;
4899 }
4900
4901 /**
4902 * If any of the given 'sigs' is contained in the existing signatures,
4903 * then add in any new signatures found in 'sigs'. This is used for
4904 * including a new package into an existing shared user id.
4905 */
4906 boolean mergeSignatures(Signature[] sigs, boolean update) {
4907 if (mSignatures == null) {
4908 if (update) {
4909 assignSignatures(sigs);
4910 }
4911 return true;
4912 }
4913 if (sigs == null) {
4914 return false;
4915 }
4916
4917 Signature[] added = null;
4918 int addedCount = 0;
4919 boolean haveMatch = false;
4920 for (int i=0; i<sigs.length; i++) {
4921 Signature sig = sigs[i];
4922 boolean found = false;
4923 for (int j=0; j<mSignatures.length; j++) {
4924 if (mSignatures[j].equals(sig)) {
4925 found = true;
4926 haveMatch = true;
4927 break;
4928 }
4929 }
4930
4931 if (!found) {
4932 if (added == null) {
4933 added = new Signature[sigs.length];
4934 }
4935 added[i] = sig;
4936 addedCount++;
4937 }
4938 }
4939
4940 if (!haveMatch) {
4941 // Nothing matched -- reject the new signatures.
4942 return false;
4943 }
4944 if (added == null) {
4945 // Completely matched -- nothing else to do.
4946 return true;
4947 }
4948
4949 // Add additional signatures in.
4950 if (update) {
4951 Signature[] total = new Signature[addedCount+mSignatures.length];
4952 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
4953 int j = mSignatures.length;
4954 for (int i=0; i<added.length; i++) {
4955 if (added[i] != null) {
4956 total[j] = added[i];
4957 j++;
4958 }
4959 }
4960 mSignatures = total;
4961 }
4962 return true;
4963 }
4964
4965 private void assignSignatures(Signature[] sigs) {
4966 if (sigs == null) {
4967 mSignatures = null;
4968 return;
4969 }
4970 mSignatures = new Signature[sigs.length];
4971 for (int i=0; i<sigs.length; i++) {
4972 mSignatures[i] = sigs[i];
4973 }
4974 }
4975
4976 @Override
4977 public String toString() {
4978 StringBuffer buf = new StringBuffer(128);
4979 buf.append("PackageSignatures{");
4980 buf.append(Integer.toHexString(System.identityHashCode(this)));
4981 buf.append(" [");
4982 if (mSignatures != null) {
4983 for (int i=0; i<mSignatures.length; i++) {
4984 if (i > 0) buf.append(", ");
4985 buf.append(Integer.toHexString(
4986 System.identityHashCode(mSignatures[i])));
4987 }
4988 }
4989 buf.append("]}");
4990 return buf.toString();
4991 }
4992 }
4993
4994 static class PreferredActivity extends IntentFilter {
4995 final int mMatch;
4996 final String[] mSetPackages;
4997 final String[] mSetClasses;
4998 final String[] mSetComponents;
4999 final ComponentName mActivity;
5000 final String mShortActivity;
5001 String mParseError;
5002
5003 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5004 ComponentName activity) {
5005 super(filter);
5006 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5007 mActivity = activity;
5008 mShortActivity = activity.flattenToShortString();
5009 mParseError = null;
5010 if (set != null) {
5011 final int N = set.length;
5012 String[] myPackages = new String[N];
5013 String[] myClasses = new String[N];
5014 String[] myComponents = new String[N];
5015 for (int i=0; i<N; i++) {
5016 ComponentName cn = set[i];
5017 if (cn == null) {
5018 mSetPackages = null;
5019 mSetClasses = null;
5020 mSetComponents = null;
5021 return;
5022 }
5023 myPackages[i] = cn.getPackageName().intern();
5024 myClasses[i] = cn.getClassName().intern();
5025 myComponents[i] = cn.flattenToShortString().intern();
5026 }
5027 mSetPackages = myPackages;
5028 mSetClasses = myClasses;
5029 mSetComponents = myComponents;
5030 } else {
5031 mSetPackages = null;
5032 mSetClasses = null;
5033 mSetComponents = null;
5034 }
5035 }
5036
5037 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5038 IOException {
5039 mShortActivity = parser.getAttributeValue(null, "name");
5040 mActivity = ComponentName.unflattenFromString(mShortActivity);
5041 if (mActivity == null) {
5042 mParseError = "Bad activity name " + mShortActivity;
5043 }
5044 String matchStr = parser.getAttributeValue(null, "match");
5045 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5046 String setCountStr = parser.getAttributeValue(null, "set");
5047 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5048
5049 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5050 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5051 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5052
5053 int setPos = 0;
5054
5055 int outerDepth = parser.getDepth();
5056 int type;
5057 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5058 && (type != XmlPullParser.END_TAG
5059 || parser.getDepth() > outerDepth)) {
5060 if (type == XmlPullParser.END_TAG
5061 || type == XmlPullParser.TEXT) {
5062 continue;
5063 }
5064
5065 String tagName = parser.getName();
5066 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5067 // + parser.getDepth() + " tag=" + tagName);
5068 if (tagName.equals("set")) {
5069 String name = parser.getAttributeValue(null, "name");
5070 if (name == null) {
5071 if (mParseError == null) {
5072 mParseError = "No name in set tag in preferred activity "
5073 + mShortActivity;
5074 }
5075 } else if (setPos >= setCount) {
5076 if (mParseError == null) {
5077 mParseError = "Too many set tags in preferred activity "
5078 + mShortActivity;
5079 }
5080 } else {
5081 ComponentName cn = ComponentName.unflattenFromString(name);
5082 if (cn == null) {
5083 if (mParseError == null) {
5084 mParseError = "Bad set name " + name + " in preferred activity "
5085 + mShortActivity;
5086 }
5087 } else {
5088 myPackages[setPos] = cn.getPackageName();
5089 myClasses[setPos] = cn.getClassName();
5090 myComponents[setPos] = name;
5091 setPos++;
5092 }
5093 }
5094 XmlUtils.skipCurrentTag(parser);
5095 } else if (tagName.equals("filter")) {
5096 //Log.i(TAG, "Starting to parse filter...");
5097 readFromXml(parser);
5098 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5099 // + parser.getDepth() + " tag=" + parser.getName());
5100 } else {
5101 reportSettingsProblem(Log.WARN,
5102 "Unknown element under <preferred-activities>: "
5103 + parser.getName());
5104 XmlUtils.skipCurrentTag(parser);
5105 }
5106 }
5107
5108 if (setPos != setCount) {
5109 if (mParseError == null) {
5110 mParseError = "Not enough set tags (expected " + setCount
5111 + " but found " + setPos + ") in " + mShortActivity;
5112 }
5113 }
5114
5115 mSetPackages = myPackages;
5116 mSetClasses = myClasses;
5117 mSetComponents = myComponents;
5118 }
5119
5120 public void writeToXml(XmlSerializer serializer) throws IOException {
5121 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5122 serializer.attribute(null, "name", mShortActivity);
5123 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5124 serializer.attribute(null, "set", Integer.toString(NS));
5125 for (int s=0; s<NS; s++) {
5126 serializer.startTag(null, "set");
5127 serializer.attribute(null, "name", mSetComponents[s]);
5128 serializer.endTag(null, "set");
5129 }
5130 serializer.startTag(null, "filter");
5131 super.writeToXml(serializer);
5132 serializer.endTag(null, "filter");
5133 }
5134
5135 boolean sameSet(List<ResolveInfo> query, int priority) {
5136 if (mSetPackages == null) return false;
5137 final int NQ = query.size();
5138 final int NS = mSetPackages.length;
5139 int numMatch = 0;
5140 for (int i=0; i<NQ; i++) {
5141 ResolveInfo ri = query.get(i);
5142 if (ri.priority != priority) continue;
5143 ActivityInfo ai = ri.activityInfo;
5144 boolean good = false;
5145 for (int j=0; j<NS; j++) {
5146 if (mSetPackages[j].equals(ai.packageName)
5147 && mSetClasses[j].equals(ai.name)) {
5148 numMatch++;
5149 good = true;
5150 break;
5151 }
5152 }
5153 if (!good) return false;
5154 }
5155 return numMatch == NS;
5156 }
5157 }
5158
5159 static class GrantedPermissions {
5160 final int pkgFlags;
5161
5162 HashSet<String> grantedPermissions = new HashSet<String>();
5163 int[] gids;
5164
5165 HashSet<String> loadedPermissions = new HashSet<String>();
5166
5167 GrantedPermissions(int pkgFlags) {
5168 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5169 }
5170 }
5171
5172 /**
5173 * Settings base class for pending and resolved classes.
5174 */
5175 static class PackageSettingBase extends GrantedPermissions {
5176 final String name;
5177 final File codePath;
5178 final String codePathString;
5179 final File resourcePath;
5180 final String resourcePathString;
5181 private long timeStamp;
5182 private String timeStampString = "0";
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005183 final int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184
5185 PackageSignatures signatures = new PackageSignatures();
5186
5187 boolean permissionsFixed;
5188
5189 /* Explicitly disabled components */
5190 HashSet<String> disabledComponents = new HashSet<String>(0);
5191 /* Explicitly enabled components */
5192 HashSet<String> enabledComponents = new HashSet<String>(0);
5193 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5194 int installStatus = PKG_INSTALL_COMPLETE;
5195
5196 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005197 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 super(pkgFlags);
5199 this.name = name;
5200 this.codePath = codePath;
5201 this.codePathString = codePath.toString();
5202 this.resourcePath = resourcePath;
5203 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005204 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 }
5206
5207 public void setInstallStatus(int newStatus) {
5208 installStatus = newStatus;
5209 }
5210
5211 public int getInstallStatus() {
5212 return installStatus;
5213 }
5214
5215 public void setTimeStamp(long newStamp) {
5216 if (newStamp != timeStamp) {
5217 timeStamp = newStamp;
5218 timeStampString = Long.toString(newStamp);
5219 }
5220 }
5221
5222 public void setTimeStamp(long newStamp, String newStampStr) {
5223 timeStamp = newStamp;
5224 timeStampString = newStampStr;
5225 }
5226
5227 public long getTimeStamp() {
5228 return timeStamp;
5229 }
5230
5231 public String getTimeStampStr() {
5232 return timeStampString;
5233 }
5234
5235 public void copyFrom(PackageSettingBase base) {
5236 grantedPermissions = base.grantedPermissions;
5237 gids = base.gids;
5238 loadedPermissions = base.loadedPermissions;
5239
5240 timeStamp = base.timeStamp;
5241 timeStampString = base.timeStampString;
5242 signatures = base.signatures;
5243 permissionsFixed = base.permissionsFixed;
5244 disabledComponents = base.disabledComponents;
5245 enabledComponents = base.enabledComponents;
5246 enabled = base.enabled;
5247 installStatus = base.installStatus;
5248 }
5249
5250 void enableComponentLP(String componentClassName) {
5251 disabledComponents.remove(componentClassName);
5252 enabledComponents.add(componentClassName);
5253 }
5254
5255 void disableComponentLP(String componentClassName) {
5256 enabledComponents.remove(componentClassName);
5257 disabledComponents.add(componentClassName);
5258 }
5259
5260 void restoreComponentLP(String componentClassName) {
5261 enabledComponents.remove(componentClassName);
5262 disabledComponents.remove(componentClassName);
5263 }
5264
5265 int currentEnabledStateLP(String componentName) {
5266 if (enabledComponents.contains(componentName)) {
5267 return COMPONENT_ENABLED_STATE_ENABLED;
5268 } else if (disabledComponents.contains(componentName)) {
5269 return COMPONENT_ENABLED_STATE_DISABLED;
5270 } else {
5271 return COMPONENT_ENABLED_STATE_DEFAULT;
5272 }
5273 }
5274 }
5275
5276 /**
5277 * Settings data for a particular package we know about.
5278 */
5279 static final class PackageSetting extends PackageSettingBase {
5280 int userId;
5281 PackageParser.Package pkg;
5282 SharedUserSetting sharedUser;
5283
5284 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005285 int pVersionCode, int pkgFlags) {
5286 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
5288
5289 @Override
5290 public String toString() {
5291 return "PackageSetting{"
5292 + Integer.toHexString(System.identityHashCode(this))
5293 + " " + name + "/" + userId + "}";
5294 }
5295 }
5296
5297 /**
5298 * Settings data for a particular shared user ID we know about.
5299 */
5300 static final class SharedUserSetting extends GrantedPermissions {
5301 final String name;
5302 int userId;
5303 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5304 final PackageSignatures signatures = new PackageSignatures();
5305
5306 SharedUserSetting(String _name, int _pkgFlags) {
5307 super(_pkgFlags);
5308 name = _name;
5309 }
5310
5311 @Override
5312 public String toString() {
5313 return "SharedUserSetting{"
5314 + Integer.toHexString(System.identityHashCode(this))
5315 + " " + name + "/" + userId + "}";
5316 }
5317 }
5318
5319 /**
5320 * Holds information about dynamic settings.
5321 */
5322 private static final class Settings {
5323 private final File mSettingsFilename;
5324 private final File mBackupSettingsFilename;
5325 private final HashMap<String, PackageSetting> mPackages =
5326 new HashMap<String, PackageSetting>();
5327 // The user's preferred packages/applications, in order of preference.
5328 // First is the most preferred.
5329 private final ArrayList<PackageSetting> mPreferredPackages =
5330 new ArrayList<PackageSetting>();
5331 // List of replaced system applications
5332 final HashMap<String, PackageSetting> mDisabledSysPackages =
5333 new HashMap<String, PackageSetting>();
5334
5335 // The user's preferred activities associated with particular intent
5336 // filters.
5337 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5338 new IntentResolver<PreferredActivity, PreferredActivity>() {
5339 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005340 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005342 out.print(prefix); out.print(
5343 Integer.toHexString(System.identityHashCode(filter)));
5344 out.print(' ');
5345 out.print(filter.mActivity.flattenToShortString());
5346 out.print(" match=0x");
5347 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005349 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005351 out.print(prefix); out.print(" ");
5352 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 }
5354 }
5355 }
5356 };
5357 private final HashMap<String, SharedUserSetting> mSharedUsers =
5358 new HashMap<String, SharedUserSetting>();
5359 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5360 private final SparseArray<Object> mOtherUserIds =
5361 new SparseArray<Object>();
5362
5363 // For reading/writing settings file.
5364 private final ArrayList<Signature> mPastSignatures =
5365 new ArrayList<Signature>();
5366
5367 // Mapping from permission names to info about them.
5368 final HashMap<String, BasePermission> mPermissions =
5369 new HashMap<String, BasePermission>();
5370
5371 // Mapping from permission tree names to info about them.
5372 final HashMap<String, BasePermission> mPermissionTrees =
5373 new HashMap<String, BasePermission>();
5374
5375 private final ArrayList<String> mPendingPreferredPackages
5376 = new ArrayList<String>();
5377
5378 private final StringBuilder mReadMessages = new StringBuilder();
5379
5380 private static final class PendingPackage extends PackageSettingBase {
5381 final int sharedId;
5382
5383 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005384 int sharedId, int pVersionCode, int pkgFlags) {
5385 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 this.sharedId = sharedId;
5387 }
5388 }
5389 private final ArrayList<PendingPackage> mPendingPackages
5390 = new ArrayList<PendingPackage>();
5391
5392 Settings() {
5393 File dataDir = Environment.getDataDirectory();
5394 File systemDir = new File(dataDir, "system");
5395 systemDir.mkdirs();
5396 FileUtils.setPermissions(systemDir.toString(),
5397 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5398 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5399 -1, -1);
5400 mSettingsFilename = new File(systemDir, "packages.xml");
5401 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5402 }
5403
5404 PackageSetting getPackageLP(PackageParser.Package pkg,
5405 SharedUserSetting sharedUser, File codePath, File resourcePath,
5406 int pkgFlags, boolean create, boolean add) {
5407 final String name = pkg.packageName;
5408 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005409 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410
5411 if (p != null) {
5412 p.pkg = pkg;
5413 }
5414 return p;
5415 }
5416
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005417 PackageSetting peekPackageLP(String name) {
5418 return mPackages.get(name);
5419 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 PackageSetting p = mPackages.get(name);
5421 if (p != null && p.codePath.getPath().equals(codePath)) {
5422 return p;
5423 }
5424 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005425 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 }
5427
5428 void setInstallStatus(String pkgName, int status) {
5429 PackageSetting p = mPackages.get(pkgName);
5430 if(p != null) {
5431 if(p.getInstallStatus() != status) {
5432 p.setInstallStatus(status);
5433 }
5434 }
5435 }
5436
5437 int getInstallStatus(String pkgName) {
5438 PackageSetting p = mPackages.get(pkgName);
5439 if(p != null) {
5440 return p.getInstallStatus();
5441 }
5442 return -1;
5443 }
5444
5445 SharedUserSetting getSharedUserLP(String name,
5446 int pkgFlags, boolean create) {
5447 SharedUserSetting s = mSharedUsers.get(name);
5448 if (s == null) {
5449 if (!create) {
5450 return null;
5451 }
5452 s = new SharedUserSetting(name, pkgFlags);
5453 if (MULTIPLE_APPLICATION_UIDS) {
5454 s.userId = newUserIdLP(s);
5455 } else {
5456 s.userId = FIRST_APPLICATION_UID;
5457 }
5458 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
5459 // < 0 means we couldn't assign a userid; fall out and return
5460 // s, which is currently null
5461 if (s.userId >= 0) {
5462 mSharedUsers.put(name, s);
5463 }
5464 }
5465
5466 return s;
5467 }
5468
5469 int disableSystemPackageLP(String name) {
5470 PackageSetting p = mPackages.get(name);
5471 if(p == null) {
5472 Log.w(TAG, "Package:"+name+" is not an installed package");
5473 return -1;
5474 }
5475 PackageSetting dp = mDisabledSysPackages.get(name);
5476 // always make sure the system package code and resource paths dont change
5477 if(dp == null) {
5478 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5479 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5480 }
5481 mDisabledSysPackages.put(name, p);
5482 }
5483 return removePackageLP(name);
5484 }
5485
5486 PackageSetting enableSystemPackageLP(String name) {
5487 PackageSetting p = mDisabledSysPackages.get(name);
5488 if(p == null) {
5489 Log.w(TAG, "Package:"+name+" is not disabled");
5490 return null;
5491 }
5492 // Reset flag in ApplicationInfo object
5493 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5494 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5495 }
5496 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005497 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 mDisabledSysPackages.remove(name);
5499 return ret;
5500 }
5501
5502 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005503 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 PackageSetting p = mPackages.get(name);
5505 if (p != null) {
5506 if (p.userId == uid) {
5507 return p;
5508 }
5509 reportSettingsProblem(Log.ERROR,
5510 "Adding duplicate package, keeping first: " + name);
5511 return null;
5512 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005513 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 p.userId = uid;
5515 if (addUserIdLP(uid, p, name)) {
5516 mPackages.put(name, p);
5517 return p;
5518 }
5519 return null;
5520 }
5521
5522 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
5523 SharedUserSetting s = mSharedUsers.get(name);
5524 if (s != null) {
5525 if (s.userId == uid) {
5526 return s;
5527 }
5528 reportSettingsProblem(Log.ERROR,
5529 "Adding duplicate shared user, keeping first: " + name);
5530 return null;
5531 }
5532 s = new SharedUserSetting(name, pkgFlags);
5533 s.userId = uid;
5534 if (addUserIdLP(uid, s, name)) {
5535 mSharedUsers.put(name, s);
5536 return s;
5537 }
5538 return null;
5539 }
5540
5541 private PackageSetting getPackageLP(String name,
5542 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005543 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 PackageSetting p = mPackages.get(name);
5545 if (p != null) {
5546 if (!p.codePath.equals(codePath)) {
5547 // Check to see if its a disabled system app
5548 PackageSetting ps = mDisabledSysPackages.get(name);
5549 if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
5550 // Could be a replaced system package
5551 // Note that if the user replaced a system app, the user has to physically
5552 // delete the new one in order to revert to the system app. So even
5553 // if the user updated the system app via an update, the user still
5554 // has to delete the one installed in the data partition in order to pick up the
5555 // new system package.
5556 return p;
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07005557 } else if ((p.pkg != null) && (p.pkg.applicationInfo != null) &&
5558 ((p.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
5559 // Check for non-system apps
5560 reportSettingsProblem(Log.WARN,
5561 "Package " + name + " codePath changed from " + p.codePath
5562 + " to " + codePath + "; Retaining data and using new code");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 } else {
5564 reportSettingsProblem(Log.WARN,
5565 "Package " + name + " codePath changed from " + p.codePath
5566 + " to " + codePath + "; replacing with new");
5567 p = null;
5568 }
5569 } else if (p.sharedUser != sharedUser) {
5570 reportSettingsProblem(Log.WARN,
5571 "Package " + name + " shared user changed from "
5572 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
5573 + " to "
5574 + (sharedUser != null ? sharedUser.name : "<nothing>")
5575 + "; replacing with new");
5576 p = null;
5577 }
5578 }
5579 if (p == null) {
5580 // Create a new PackageSettings entry. this can end up here because
5581 // of code path mismatch or user id mismatch of an updated system partition
5582 if (!create) {
5583 return null;
5584 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005585 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 p.setTimeStamp(codePath.lastModified());
5587 if (sharedUser != null) {
5588 p.userId = sharedUser.userId;
5589 } else if (MULTIPLE_APPLICATION_UIDS) {
5590 p.userId = newUserIdLP(p);
5591 } else {
5592 p.userId = FIRST_APPLICATION_UID;
5593 }
5594 if (p.userId < 0) {
5595 reportSettingsProblem(Log.WARN,
5596 "Package " + name + " could not be assigned a valid uid");
5597 return null;
5598 }
5599 if (add) {
5600 // Finish adding new package by adding it and updating shared
5601 // user preferences
5602 insertPackageSettingLP(p, name, sharedUser);
5603 }
5604 }
5605 return p;
5606 }
5607
5608 // Utility method that adds a PackageSetting to mPackages and
5609 // completes updating the shared user attributes
5610 private void insertPackageSettingLP(PackageSetting p, String name,
5611 SharedUserSetting sharedUser) {
5612 mPackages.put(name, p);
5613 if (sharedUser != null) {
5614 if (p.sharedUser != null && p.sharedUser != sharedUser) {
5615 reportSettingsProblem(Log.ERROR,
5616 "Package " + p.name + " was user "
5617 + p.sharedUser + " but is now " + sharedUser
5618 + "; I am not changing its files so it will probably fail!");
5619 p.sharedUser.packages.remove(p);
5620 } else if (p.userId != sharedUser.userId) {
5621 reportSettingsProblem(Log.ERROR,
5622 "Package " + p.name + " was user id " + p.userId
5623 + " but is now user " + sharedUser
5624 + " with id " + sharedUser.userId
5625 + "; I am not changing its files so it will probably fail!");
5626 }
5627
5628 sharedUser.packages.add(p);
5629 p.sharedUser = sharedUser;
5630 p.userId = sharedUser.userId;
5631 }
5632 }
5633
5634 private void updateSharedUserPerms (PackageSetting deletedPs) {
5635 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
5636 Log.i(TAG, "Trying to update info for null package. Just ignoring");
5637 return;
5638 }
5639 // No sharedUserId
5640 if (deletedPs.sharedUser == null) {
5641 return;
5642 }
5643 SharedUserSetting sus = deletedPs.sharedUser;
5644 // Update permissions
5645 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
5646 boolean used = false;
5647 if (!sus.grantedPermissions.contains (eachPerm)) {
5648 continue;
5649 }
5650 for (PackageSetting pkg:sus.packages) {
5651 if (pkg.grantedPermissions.contains (eachPerm)) {
5652 used = true;
5653 break;
5654 }
5655 }
5656 if (!used) {
5657 // can safely delete this permission from list
5658 sus.grantedPermissions.remove(eachPerm);
5659 sus.loadedPermissions.remove(eachPerm);
5660 }
5661 }
5662 // Update gids
5663 int newGids[] = null;
5664 for (PackageSetting pkg:sus.packages) {
5665 newGids = appendInts(newGids, pkg.gids);
5666 }
5667 sus.gids = newGids;
5668 }
5669
5670 private int removePackageLP(String name) {
5671 PackageSetting p = mPackages.get(name);
5672 if (p != null) {
5673 mPackages.remove(name);
5674 if (p.sharedUser != null) {
5675 p.sharedUser.packages.remove(p);
5676 if (p.sharedUser.packages.size() == 0) {
5677 mSharedUsers.remove(p.sharedUser.name);
5678 removeUserIdLP(p.sharedUser.userId);
5679 return p.sharedUser.userId;
5680 }
5681 } else {
5682 removeUserIdLP(p.userId);
5683 return p.userId;
5684 }
5685 }
5686 return -1;
5687 }
5688
5689 private boolean addUserIdLP(int uid, Object obj, Object name) {
5690 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
5691 return false;
5692 }
5693
5694 if (uid >= FIRST_APPLICATION_UID) {
5695 int N = mUserIds.size();
5696 final int index = uid - FIRST_APPLICATION_UID;
5697 while (index >= N) {
5698 mUserIds.add(null);
5699 N++;
5700 }
5701 if (mUserIds.get(index) != null) {
5702 reportSettingsProblem(Log.ERROR,
5703 "Adding duplicate shared id: " + uid
5704 + " name=" + name);
5705 return false;
5706 }
5707 mUserIds.set(index, obj);
5708 } else {
5709 if (mOtherUserIds.get(uid) != null) {
5710 reportSettingsProblem(Log.ERROR,
5711 "Adding duplicate shared id: " + uid
5712 + " name=" + name);
5713 return false;
5714 }
5715 mOtherUserIds.put(uid, obj);
5716 }
5717 return true;
5718 }
5719
5720 public Object getUserIdLP(int uid) {
5721 if (uid >= FIRST_APPLICATION_UID) {
5722 int N = mUserIds.size();
5723 final int index = uid - FIRST_APPLICATION_UID;
5724 return index < N ? mUserIds.get(index) : null;
5725 } else {
5726 return mOtherUserIds.get(uid);
5727 }
5728 }
5729
5730 private void removeUserIdLP(int uid) {
5731 if (uid >= FIRST_APPLICATION_UID) {
5732 int N = mUserIds.size();
5733 final int index = uid - FIRST_APPLICATION_UID;
5734 if (index < N) mUserIds.set(index, null);
5735 } else {
5736 mOtherUserIds.remove(uid);
5737 }
5738 }
5739
5740 void writeLP() {
5741 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
5742
5743 // Keep the old settings around until we know the new ones have
5744 // been successfully written.
5745 if (mSettingsFilename.exists()) {
5746 if (mBackupSettingsFilename.exists()) {
5747 mBackupSettingsFilename.delete();
5748 }
5749 mSettingsFilename.renameTo(mBackupSettingsFilename);
5750 }
5751
5752 mPastSignatures.clear();
5753
5754 try {
5755 FileOutputStream str = new FileOutputStream(mSettingsFilename);
5756
5757 //XmlSerializer serializer = XmlUtils.serializerInstance();
5758 XmlSerializer serializer = new FastXmlSerializer();
5759 serializer.setOutput(str, "utf-8");
5760 serializer.startDocument(null, true);
5761 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
5762
5763 serializer.startTag(null, "packages");
5764
5765 serializer.startTag(null, "permission-trees");
5766 for (BasePermission bp : mPermissionTrees.values()) {
5767 writePermission(serializer, bp);
5768 }
5769 serializer.endTag(null, "permission-trees");
5770
5771 serializer.startTag(null, "permissions");
5772 for (BasePermission bp : mPermissions.values()) {
5773 writePermission(serializer, bp);
5774 }
5775 serializer.endTag(null, "permissions");
5776
5777 for (PackageSetting pkg : mPackages.values()) {
5778 writePackage(serializer, pkg);
5779 }
5780
5781 for (PackageSetting pkg : mDisabledSysPackages.values()) {
5782 writeDisabledSysPackage(serializer, pkg);
5783 }
5784
5785 serializer.startTag(null, "preferred-packages");
5786 int N = mPreferredPackages.size();
5787 for (int i=0; i<N; i++) {
5788 PackageSetting pkg = mPreferredPackages.get(i);
5789 serializer.startTag(null, "item");
5790 serializer.attribute(null, "name", pkg.name);
5791 serializer.endTag(null, "item");
5792 }
5793 serializer.endTag(null, "preferred-packages");
5794
5795 serializer.startTag(null, "preferred-activities");
5796 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
5797 serializer.startTag(null, "item");
5798 pa.writeToXml(serializer);
5799 serializer.endTag(null, "item");
5800 }
5801 serializer.endTag(null, "preferred-activities");
5802
5803 for (SharedUserSetting usr : mSharedUsers.values()) {
5804 serializer.startTag(null, "shared-user");
5805 serializer.attribute(null, "name", usr.name);
5806 serializer.attribute(null, "userId",
5807 Integer.toString(usr.userId));
5808 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
5809 serializer.startTag(null, "perms");
5810 for (String name : usr.grantedPermissions) {
5811 serializer.startTag(null, "item");
5812 serializer.attribute(null, "name", name);
5813 serializer.endTag(null, "item");
5814 }
5815 serializer.endTag(null, "perms");
5816 serializer.endTag(null, "shared-user");
5817 }
5818
5819 serializer.endTag(null, "packages");
5820
5821 serializer.endDocument();
5822
5823 str.flush();
5824 str.close();
5825
5826 // New settings successfully written, old ones are no longer
5827 // needed.
5828 mBackupSettingsFilename.delete();
5829 FileUtils.setPermissions(mSettingsFilename.toString(),
5830 FileUtils.S_IRUSR|FileUtils.S_IWUSR
5831 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
5832 |FileUtils.S_IROTH,
5833 -1, -1);
5834
5835 } catch(XmlPullParserException e) {
5836 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5837
5838 } catch(java.io.IOException e) {
5839 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5840
5841 }
5842
5843 //Debug.stopMethodTracing();
5844 }
5845
5846 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
5847 throws java.io.IOException {
5848 serializer.startTag(null, "updated-package");
5849 serializer.attribute(null, "name", pkg.name);
5850 serializer.attribute(null, "codePath", pkg.codePathString);
5851 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005852 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5854 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5855 }
5856 if (pkg.sharedUser == null) {
5857 serializer.attribute(null, "userId",
5858 Integer.toString(pkg.userId));
5859 } else {
5860 serializer.attribute(null, "sharedUserId",
5861 Integer.toString(pkg.userId));
5862 }
5863 serializer.startTag(null, "perms");
5864 if (pkg.sharedUser == null) {
5865 // If this is a shared user, the permissions will
5866 // be written there. We still need to write an
5867 // empty permissions list so permissionsFixed will
5868 // be set.
5869 for (final String name : pkg.grantedPermissions) {
5870 BasePermission bp = mPermissions.get(name);
5871 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
5872 // We only need to write signature or system permissions but this wont
5873 // match the semantics of grantedPermissions. So write all permissions.
5874 serializer.startTag(null, "item");
5875 serializer.attribute(null, "name", name);
5876 serializer.endTag(null, "item");
5877 }
5878 }
5879 }
5880 serializer.endTag(null, "perms");
5881 serializer.endTag(null, "updated-package");
5882 }
5883
5884 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
5885 throws java.io.IOException {
5886 serializer.startTag(null, "package");
5887 serializer.attribute(null, "name", pkg.name);
5888 serializer.attribute(null, "codePath", pkg.codePathString);
5889 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5890 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5891 }
5892 serializer.attribute(null, "system",
5893 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
5894 ? "true" : "false");
5895 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005896 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 if (pkg.sharedUser == null) {
5898 serializer.attribute(null, "userId",
5899 Integer.toString(pkg.userId));
5900 } else {
5901 serializer.attribute(null, "sharedUserId",
5902 Integer.toString(pkg.userId));
5903 }
5904 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
5905 serializer.attribute(null, "enabled",
5906 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
5907 ? "true" : "false");
5908 }
5909 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
5910 serializer.attribute(null, "installStatus", "false");
5911 }
5912 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
5913 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5914 serializer.startTag(null, "perms");
5915 if (pkg.sharedUser == null) {
5916 // If this is a shared user, the permissions will
5917 // be written there. We still need to write an
5918 // empty permissions list so permissionsFixed will
5919 // be set.
5920 for (final String name : pkg.grantedPermissions) {
5921 serializer.startTag(null, "item");
5922 serializer.attribute(null, "name", name);
5923 serializer.endTag(null, "item");
5924 }
5925 }
5926 serializer.endTag(null, "perms");
5927 }
5928 if (pkg.disabledComponents.size() > 0) {
5929 serializer.startTag(null, "disabled-components");
5930 for (final String name : pkg.disabledComponents) {
5931 serializer.startTag(null, "item");
5932 serializer.attribute(null, "name", name);
5933 serializer.endTag(null, "item");
5934 }
5935 serializer.endTag(null, "disabled-components");
5936 }
5937 if (pkg.enabledComponents.size() > 0) {
5938 serializer.startTag(null, "enabled-components");
5939 for (final String name : pkg.enabledComponents) {
5940 serializer.startTag(null, "item");
5941 serializer.attribute(null, "name", name);
5942 serializer.endTag(null, "item");
5943 }
5944 serializer.endTag(null, "enabled-components");
5945 }
5946 serializer.endTag(null, "package");
5947 }
5948
5949 void writePermission(XmlSerializer serializer, BasePermission bp)
5950 throws XmlPullParserException, java.io.IOException {
5951 if (bp.type != BasePermission.TYPE_BUILTIN
5952 && bp.sourcePackage != null) {
5953 serializer.startTag(null, "item");
5954 serializer.attribute(null, "name", bp.name);
5955 serializer.attribute(null, "package", bp.sourcePackage);
5956 if (DEBUG_SETTINGS) Log.v(TAG,
5957 "Writing perm: name=" + bp.name + " type=" + bp.type);
5958 if (bp.type == BasePermission.TYPE_DYNAMIC) {
5959 PermissionInfo pi = bp.perm != null ? bp.perm.info
5960 : bp.pendingInfo;
5961 if (pi != null) {
5962 serializer.attribute(null, "type", "dynamic");
5963 if (pi.icon != 0) {
5964 serializer.attribute(null, "icon",
5965 Integer.toString(pi.icon));
5966 }
5967 if (pi.nonLocalizedLabel != null) {
5968 serializer.attribute(null, "label",
5969 pi.nonLocalizedLabel.toString());
5970 }
5971 if (pi.protectionLevel !=
5972 PermissionInfo.PROTECTION_NORMAL) {
5973 serializer.attribute(null, "protection",
5974 Integer.toString(pi.protectionLevel));
5975 }
5976 }
5977 }
5978 serializer.endTag(null, "item");
5979 }
5980 }
5981
5982 String getReadMessagesLP() {
5983 return mReadMessages.toString();
5984 }
5985
5986 ArrayList<String> getListOfIncompleteInstallPackages() {
5987 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
5988 Iterator<String> its = kList.iterator();
5989 ArrayList<String> ret = new ArrayList<String>();
5990 while(its.hasNext()) {
5991 String key = its.next();
5992 PackageSetting ps = mPackages.get(key);
5993 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
5994 ret.add(key);
5995 }
5996 }
5997 return ret;
5998 }
5999
6000 boolean readLP() {
6001 FileInputStream str = null;
6002 if (mBackupSettingsFilename.exists()) {
6003 try {
6004 str = new FileInputStream(mBackupSettingsFilename);
6005 mReadMessages.append("Reading from backup settings file\n");
6006 Log.i(TAG, "Reading from backup settings file!");
6007 } catch (java.io.IOException e) {
6008 // We'll try for the normal settings file.
6009 }
6010 }
6011
6012 mPastSignatures.clear();
6013
6014 try {
6015 if (str == null) {
6016 if (!mSettingsFilename.exists()) {
6017 mReadMessages.append("No settings file found\n");
6018 Log.i(TAG, "No current settings file!");
6019 return false;
6020 }
6021 str = new FileInputStream(mSettingsFilename);
6022 }
6023 XmlPullParser parser = Xml.newPullParser();
6024 parser.setInput(str, null);
6025
6026 int type;
6027 while ((type=parser.next()) != XmlPullParser.START_TAG
6028 && type != XmlPullParser.END_DOCUMENT) {
6029 ;
6030 }
6031
6032 if (type != XmlPullParser.START_TAG) {
6033 mReadMessages.append("No start tag found in settings file\n");
6034 Log.e(TAG, "No start tag found in package manager settings");
6035 return false;
6036 }
6037
6038 int outerDepth = parser.getDepth();
6039 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6040 && (type != XmlPullParser.END_TAG
6041 || parser.getDepth() > outerDepth)) {
6042 if (type == XmlPullParser.END_TAG
6043 || type == XmlPullParser.TEXT) {
6044 continue;
6045 }
6046
6047 String tagName = parser.getName();
6048 if (tagName.equals("package")) {
6049 readPackageLP(parser);
6050 } else if (tagName.equals("permissions")) {
6051 readPermissionsLP(mPermissions, parser);
6052 } else if (tagName.equals("permission-trees")) {
6053 readPermissionsLP(mPermissionTrees, parser);
6054 } else if (tagName.equals("shared-user")) {
6055 readSharedUserLP(parser);
6056 } else if (tagName.equals("preferred-packages")) {
6057 readPreferredPackagesLP(parser);
6058 } else if (tagName.equals("preferred-activities")) {
6059 readPreferredActivitiesLP(parser);
6060 } else if(tagName.equals("updated-package")) {
6061 readDisabledSysPackageLP(parser);
6062 } else {
6063 Log.w(TAG, "Unknown element under <packages>: "
6064 + parser.getName());
6065 XmlUtils.skipCurrentTag(parser);
6066 }
6067 }
6068
6069 str.close();
6070
6071 } catch(XmlPullParserException e) {
6072 mReadMessages.append("Error reading: " + e.toString());
6073 Log.e(TAG, "Error reading package manager settings", e);
6074
6075 } catch(java.io.IOException e) {
6076 mReadMessages.append("Error reading: " + e.toString());
6077 Log.e(TAG, "Error reading package manager settings", e);
6078
6079 }
6080
6081 int N = mPendingPackages.size();
6082 for (int i=0; i<N; i++) {
6083 final PendingPackage pp = mPendingPackages.get(i);
6084 Object idObj = getUserIdLP(pp.sharedId);
6085 if (idObj != null && idObj instanceof SharedUserSetting) {
6086 PackageSetting p = getPackageLP(pp.name,
6087 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006088 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 if (p == null) {
6090 Log.w(TAG, "Unable to create application package for "
6091 + pp.name);
6092 continue;
6093 }
6094 p.copyFrom(pp);
6095 } else if (idObj != null) {
6096 String msg = "Bad package setting: package " + pp.name
6097 + " has shared uid " + pp.sharedId
6098 + " that is not a shared uid\n";
6099 mReadMessages.append(msg);
6100 Log.e(TAG, msg);
6101 } else {
6102 String msg = "Bad package setting: package " + pp.name
6103 + " has shared uid " + pp.sharedId
6104 + " that is not defined\n";
6105 mReadMessages.append(msg);
6106 Log.e(TAG, msg);
6107 }
6108 }
6109 mPendingPackages.clear();
6110
6111 N = mPendingPreferredPackages.size();
6112 mPreferredPackages.clear();
6113 for (int i=0; i<N; i++) {
6114 final String name = mPendingPreferredPackages.get(i);
6115 final PackageSetting p = mPackages.get(name);
6116 if (p != null) {
6117 mPreferredPackages.add(p);
6118 } else {
6119 Log.w(TAG, "Unknown preferred package: " + name);
6120 }
6121 }
6122 mPendingPreferredPackages.clear();
6123
6124 mReadMessages.append("Read completed successfully: "
6125 + mPackages.size() + " packages, "
6126 + mSharedUsers.size() + " shared uids\n");
6127
6128 return true;
6129 }
6130
6131 private int readInt(XmlPullParser parser, String ns, String name,
6132 int defValue) {
6133 String v = parser.getAttributeValue(ns, name);
6134 try {
6135 if (v == null) {
6136 return defValue;
6137 }
6138 return Integer.parseInt(v);
6139 } catch (NumberFormatException e) {
6140 reportSettingsProblem(Log.WARN,
6141 "Error in package manager settings: attribute " +
6142 name + " has bad integer value " + v + " at "
6143 + parser.getPositionDescription());
6144 }
6145 return defValue;
6146 }
6147
6148 private void readPermissionsLP(HashMap<String, BasePermission> out,
6149 XmlPullParser parser)
6150 throws IOException, XmlPullParserException {
6151 int outerDepth = parser.getDepth();
6152 int type;
6153 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6154 && (type != XmlPullParser.END_TAG
6155 || parser.getDepth() > outerDepth)) {
6156 if (type == XmlPullParser.END_TAG
6157 || type == XmlPullParser.TEXT) {
6158 continue;
6159 }
6160
6161 String tagName = parser.getName();
6162 if (tagName.equals("item")) {
6163 String name = parser.getAttributeValue(null, "name");
6164 String sourcePackage = parser.getAttributeValue(null, "package");
6165 String ptype = parser.getAttributeValue(null, "type");
6166 if (name != null && sourcePackage != null) {
6167 boolean dynamic = "dynamic".equals(ptype);
6168 BasePermission bp = new BasePermission(name, sourcePackage,
6169 dynamic
6170 ? BasePermission.TYPE_DYNAMIC
6171 : BasePermission.TYPE_NORMAL);
6172 if (dynamic) {
6173 PermissionInfo pi = new PermissionInfo();
6174 pi.packageName = sourcePackage.intern();
6175 pi.name = name.intern();
6176 pi.icon = readInt(parser, null, "icon", 0);
6177 pi.nonLocalizedLabel = parser.getAttributeValue(
6178 null, "label");
6179 pi.protectionLevel = readInt(parser, null, "protection",
6180 PermissionInfo.PROTECTION_NORMAL);
6181 bp.pendingInfo = pi;
6182 }
6183 out.put(bp.name, bp);
6184 } else {
6185 reportSettingsProblem(Log.WARN,
6186 "Error in package manager settings: permissions has"
6187 + " no name at " + parser.getPositionDescription());
6188 }
6189 } else {
6190 reportSettingsProblem(Log.WARN,
6191 "Unknown element reading permissions: "
6192 + parser.getName() + " at "
6193 + parser.getPositionDescription());
6194 }
6195 XmlUtils.skipCurrentTag(parser);
6196 }
6197 }
6198
6199 private void readDisabledSysPackageLP(XmlPullParser parser)
6200 throws XmlPullParserException, IOException {
6201 String name = parser.getAttributeValue(null, "name");
6202 String codePathStr = parser.getAttributeValue(null, "codePath");
6203 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6204 if(resourcePathStr == null) {
6205 resourcePathStr = codePathStr;
6206 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006207 String version = parser.getAttributeValue(null, "version");
6208 int versionCode = 0;
6209 if (version != null) {
6210 try {
6211 versionCode = Integer.parseInt(version);
6212 } catch (NumberFormatException e) {
6213 }
6214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215
6216 int pkgFlags = 0;
6217 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6218 PackageSetting ps = new PackageSetting(name,
6219 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006220 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 String timeStampStr = parser.getAttributeValue(null, "ts");
6222 if (timeStampStr != null) {
6223 try {
6224 long timeStamp = Long.parseLong(timeStampStr);
6225 ps.setTimeStamp(timeStamp, timeStampStr);
6226 } catch (NumberFormatException e) {
6227 }
6228 }
6229 String idStr = parser.getAttributeValue(null, "userId");
6230 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6231 if(ps.userId <= 0) {
6232 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6233 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6234 }
6235 int outerDepth = parser.getDepth();
6236 int type;
6237 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6238 && (type != XmlPullParser.END_TAG
6239 || parser.getDepth() > outerDepth)) {
6240 if (type == XmlPullParser.END_TAG
6241 || type == XmlPullParser.TEXT) {
6242 continue;
6243 }
6244
6245 String tagName = parser.getName();
6246 if (tagName.equals("perms")) {
6247 readGrantedPermissionsLP(parser,
6248 ps.grantedPermissions);
6249 } else {
6250 reportSettingsProblem(Log.WARN,
6251 "Unknown element under <updated-package>: "
6252 + parser.getName());
6253 XmlUtils.skipCurrentTag(parser);
6254 }
6255 }
6256 mDisabledSysPackages.put(name, ps);
6257 }
6258
6259 private void readPackageLP(XmlPullParser parser)
6260 throws XmlPullParserException, IOException {
6261 String name = null;
6262 String idStr = null;
6263 String sharedIdStr = null;
6264 String codePathStr = null;
6265 String resourcePathStr = null;
6266 String systemStr = null;
6267 int pkgFlags = 0;
6268 String timeStampStr;
6269 long timeStamp = 0;
6270 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006271 String version = null;
6272 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 try {
6274 name = parser.getAttributeValue(null, "name");
6275 idStr = parser.getAttributeValue(null, "userId");
6276 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6277 codePathStr = parser.getAttributeValue(null, "codePath");
6278 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006279 version = parser.getAttributeValue(null, "version");
6280 if (version != null) {
6281 try {
6282 versionCode = Integer.parseInt(version);
6283 } catch (NumberFormatException e) {
6284 }
6285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006286 systemStr = parser.getAttributeValue(null, "system");
6287 if (systemStr != null) {
6288 if ("true".equals(systemStr)) {
6289 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6290 }
6291 } else {
6292 // Old settings that don't specify system... just treat
6293 // them as system, good enough.
6294 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6295 }
6296 timeStampStr = parser.getAttributeValue(null, "ts");
6297 if (timeStampStr != null) {
6298 try {
6299 timeStamp = Long.parseLong(timeStampStr);
6300 } catch (NumberFormatException e) {
6301 }
6302 }
6303 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6304 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6305 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6306 if (resourcePathStr == null) {
6307 resourcePathStr = codePathStr;
6308 }
6309 if (name == null) {
6310 reportSettingsProblem(Log.WARN,
6311 "Error in package manager settings: <package> has no name at "
6312 + parser.getPositionDescription());
6313 } else if (codePathStr == null) {
6314 reportSettingsProblem(Log.WARN,
6315 "Error in package manager settings: <package> has no codePath at "
6316 + parser.getPositionDescription());
6317 } else if (userId > 0) {
6318 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006319 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6321 + ": userId=" + userId + " pkg=" + packageSetting);
6322 if (packageSetting == null) {
6323 reportSettingsProblem(Log.ERROR,
6324 "Failure adding uid " + userId
6325 + " while parsing settings at "
6326 + parser.getPositionDescription());
6327 } else {
6328 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6329 }
6330 } else if (sharedIdStr != null) {
6331 userId = sharedIdStr != null
6332 ? Integer.parseInt(sharedIdStr) : 0;
6333 if (userId > 0) {
6334 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006335 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6337 mPendingPackages.add((PendingPackage) packageSetting);
6338 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6339 + ": sharedUserId=" + userId + " pkg="
6340 + packageSetting);
6341 } else {
6342 reportSettingsProblem(Log.WARN,
6343 "Error in package manager settings: package "
6344 + name + " has bad sharedId " + sharedIdStr
6345 + " at " + parser.getPositionDescription());
6346 }
6347 } else {
6348 reportSettingsProblem(Log.WARN,
6349 "Error in package manager settings: package "
6350 + name + " has bad userId " + idStr + " at "
6351 + parser.getPositionDescription());
6352 }
6353 } catch (NumberFormatException e) {
6354 reportSettingsProblem(Log.WARN,
6355 "Error in package manager settings: package "
6356 + name + " has bad userId " + idStr + " at "
6357 + parser.getPositionDescription());
6358 }
6359 if (packageSetting != null) {
6360 final String enabledStr = parser.getAttributeValue(null, "enabled");
6361 if (enabledStr != null) {
6362 if (enabledStr.equalsIgnoreCase("true")) {
6363 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
6364 } else if (enabledStr.equalsIgnoreCase("false")) {
6365 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
6366 } else if (enabledStr.equalsIgnoreCase("default")) {
6367 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6368 } else {
6369 reportSettingsProblem(Log.WARN,
6370 "Error in package manager settings: package "
6371 + name + " has bad enabled value: " + idStr
6372 + " at " + parser.getPositionDescription());
6373 }
6374 } else {
6375 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6376 }
6377 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
6378 if (installStatusStr != null) {
6379 if (installStatusStr.equalsIgnoreCase("false")) {
6380 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
6381 } else {
6382 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
6383 }
6384 }
6385
6386 int outerDepth = parser.getDepth();
6387 int type;
6388 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6389 && (type != XmlPullParser.END_TAG
6390 || parser.getDepth() > outerDepth)) {
6391 if (type == XmlPullParser.END_TAG
6392 || type == XmlPullParser.TEXT) {
6393 continue;
6394 }
6395
6396 String tagName = parser.getName();
6397 if (tagName.equals("disabled-components")) {
6398 readDisabledComponentsLP(packageSetting, parser);
6399 } else if (tagName.equals("enabled-components")) {
6400 readEnabledComponentsLP(packageSetting, parser);
6401 } else if (tagName.equals("sigs")) {
6402 packageSetting.signatures.readXml(parser, mPastSignatures);
6403 } else if (tagName.equals("perms")) {
6404 readGrantedPermissionsLP(parser,
6405 packageSetting.loadedPermissions);
6406 packageSetting.permissionsFixed = true;
6407 } else {
6408 reportSettingsProblem(Log.WARN,
6409 "Unknown element under <package>: "
6410 + parser.getName());
6411 XmlUtils.skipCurrentTag(parser);
6412 }
6413 }
6414 } else {
6415 XmlUtils.skipCurrentTag(parser);
6416 }
6417 }
6418
6419 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
6420 XmlPullParser parser)
6421 throws IOException, XmlPullParserException {
6422 int outerDepth = parser.getDepth();
6423 int type;
6424 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6425 && (type != XmlPullParser.END_TAG
6426 || parser.getDepth() > outerDepth)) {
6427 if (type == XmlPullParser.END_TAG
6428 || type == XmlPullParser.TEXT) {
6429 continue;
6430 }
6431
6432 String tagName = parser.getName();
6433 if (tagName.equals("item")) {
6434 String name = parser.getAttributeValue(null, "name");
6435 if (name != null) {
6436 packageSetting.disabledComponents.add(name.intern());
6437 } else {
6438 reportSettingsProblem(Log.WARN,
6439 "Error in package manager settings: <disabled-components> has"
6440 + " no name at " + parser.getPositionDescription());
6441 }
6442 } else {
6443 reportSettingsProblem(Log.WARN,
6444 "Unknown element under <disabled-components>: "
6445 + parser.getName());
6446 }
6447 XmlUtils.skipCurrentTag(parser);
6448 }
6449 }
6450
6451 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
6452 XmlPullParser parser)
6453 throws IOException, XmlPullParserException {
6454 int outerDepth = parser.getDepth();
6455 int type;
6456 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6457 && (type != XmlPullParser.END_TAG
6458 || parser.getDepth() > outerDepth)) {
6459 if (type == XmlPullParser.END_TAG
6460 || type == XmlPullParser.TEXT) {
6461 continue;
6462 }
6463
6464 String tagName = parser.getName();
6465 if (tagName.equals("item")) {
6466 String name = parser.getAttributeValue(null, "name");
6467 if (name != null) {
6468 packageSetting.enabledComponents.add(name.intern());
6469 } else {
6470 reportSettingsProblem(Log.WARN,
6471 "Error in package manager settings: <enabled-components> has"
6472 + " no name at " + parser.getPositionDescription());
6473 }
6474 } else {
6475 reportSettingsProblem(Log.WARN,
6476 "Unknown element under <enabled-components>: "
6477 + parser.getName());
6478 }
6479 XmlUtils.skipCurrentTag(parser);
6480 }
6481 }
6482
6483 private void readSharedUserLP(XmlPullParser parser)
6484 throws XmlPullParserException, IOException {
6485 String name = null;
6486 String idStr = null;
6487 int pkgFlags = 0;
6488 SharedUserSetting su = null;
6489 try {
6490 name = parser.getAttributeValue(null, "name");
6491 idStr = parser.getAttributeValue(null, "userId");
6492 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6493 if ("true".equals(parser.getAttributeValue(null, "system"))) {
6494 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6495 }
6496 if (name == null) {
6497 reportSettingsProblem(Log.WARN,
6498 "Error in package manager settings: <shared-user> has no name at "
6499 + parser.getPositionDescription());
6500 } else if (userId == 0) {
6501 reportSettingsProblem(Log.WARN,
6502 "Error in package manager settings: shared-user "
6503 + name + " has bad userId " + idStr + " at "
6504 + parser.getPositionDescription());
6505 } else {
6506 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
6507 reportSettingsProblem(Log.ERROR,
6508 "Occurred while parsing settings at "
6509 + parser.getPositionDescription());
6510 }
6511 }
6512 } catch (NumberFormatException e) {
6513 reportSettingsProblem(Log.WARN,
6514 "Error in package manager settings: package "
6515 + name + " has bad userId " + idStr + " at "
6516 + parser.getPositionDescription());
6517 };
6518
6519 if (su != null) {
6520 int outerDepth = parser.getDepth();
6521 int type;
6522 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6523 && (type != XmlPullParser.END_TAG
6524 || parser.getDepth() > outerDepth)) {
6525 if (type == XmlPullParser.END_TAG
6526 || type == XmlPullParser.TEXT) {
6527 continue;
6528 }
6529
6530 String tagName = parser.getName();
6531 if (tagName.equals("sigs")) {
6532 su.signatures.readXml(parser, mPastSignatures);
6533 } else if (tagName.equals("perms")) {
6534 readGrantedPermissionsLP(parser, su.loadedPermissions);
6535 } else {
6536 reportSettingsProblem(Log.WARN,
6537 "Unknown element under <shared-user>: "
6538 + parser.getName());
6539 XmlUtils.skipCurrentTag(parser);
6540 }
6541 }
6542
6543 } else {
6544 XmlUtils.skipCurrentTag(parser);
6545 }
6546 }
6547
6548 private void readGrantedPermissionsLP(XmlPullParser parser,
6549 HashSet<String> outPerms) throws IOException, XmlPullParserException {
6550 int outerDepth = parser.getDepth();
6551 int type;
6552 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6553 && (type != XmlPullParser.END_TAG
6554 || parser.getDepth() > outerDepth)) {
6555 if (type == XmlPullParser.END_TAG
6556 || type == XmlPullParser.TEXT) {
6557 continue;
6558 }
6559
6560 String tagName = parser.getName();
6561 if (tagName.equals("item")) {
6562 String name = parser.getAttributeValue(null, "name");
6563 if (name != null) {
6564 outPerms.add(name.intern());
6565 } else {
6566 reportSettingsProblem(Log.WARN,
6567 "Error in package manager settings: <perms> has"
6568 + " no name at " + parser.getPositionDescription());
6569 }
6570 } else {
6571 reportSettingsProblem(Log.WARN,
6572 "Unknown element under <perms>: "
6573 + parser.getName());
6574 }
6575 XmlUtils.skipCurrentTag(parser);
6576 }
6577 }
6578
6579 private void readPreferredPackagesLP(XmlPullParser parser)
6580 throws XmlPullParserException, IOException {
6581 int outerDepth = parser.getDepth();
6582 int type;
6583 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6584 && (type != XmlPullParser.END_TAG
6585 || parser.getDepth() > outerDepth)) {
6586 if (type == XmlPullParser.END_TAG
6587 || type == XmlPullParser.TEXT) {
6588 continue;
6589 }
6590
6591 String tagName = parser.getName();
6592 if (tagName.equals("item")) {
6593 String name = parser.getAttributeValue(null, "name");
6594 if (name != null) {
6595 mPendingPreferredPackages.add(name);
6596 } else {
6597 reportSettingsProblem(Log.WARN,
6598 "Error in package manager settings: <preferred-package> has no name at "
6599 + parser.getPositionDescription());
6600 }
6601 } else {
6602 reportSettingsProblem(Log.WARN,
6603 "Unknown element under <preferred-packages>: "
6604 + parser.getName());
6605 }
6606 XmlUtils.skipCurrentTag(parser);
6607 }
6608 }
6609
6610 private void readPreferredActivitiesLP(XmlPullParser parser)
6611 throws XmlPullParserException, IOException {
6612 int outerDepth = parser.getDepth();
6613 int type;
6614 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6615 && (type != XmlPullParser.END_TAG
6616 || parser.getDepth() > outerDepth)) {
6617 if (type == XmlPullParser.END_TAG
6618 || type == XmlPullParser.TEXT) {
6619 continue;
6620 }
6621
6622 String tagName = parser.getName();
6623 if (tagName.equals("item")) {
6624 PreferredActivity pa = new PreferredActivity(parser);
6625 if (pa.mParseError == null) {
6626 mPreferredActivities.addFilter(pa);
6627 } else {
6628 reportSettingsProblem(Log.WARN,
6629 "Error in package manager settings: <preferred-activity> "
6630 + pa.mParseError + " at "
6631 + parser.getPositionDescription());
6632 }
6633 } else {
6634 reportSettingsProblem(Log.WARN,
6635 "Unknown element under <preferred-activities>: "
6636 + parser.getName());
6637 XmlUtils.skipCurrentTag(parser);
6638 }
6639 }
6640 }
6641
6642 // Returns -1 if we could not find an available UserId to assign
6643 private int newUserIdLP(Object obj) {
6644 // Let's be stupidly inefficient for now...
6645 final int N = mUserIds.size();
6646 for (int i=0; i<N; i++) {
6647 if (mUserIds.get(i) == null) {
6648 mUserIds.set(i, obj);
6649 return FIRST_APPLICATION_UID + i;
6650 }
6651 }
6652
6653 // None left?
6654 if (N >= MAX_APPLICATION_UIDS) {
6655 return -1;
6656 }
6657
6658 mUserIds.add(obj);
6659 return FIRST_APPLICATION_UID + N;
6660 }
6661
6662 public PackageSetting getDisabledSystemPkg(String name) {
6663 synchronized(mPackages) {
6664 PackageSetting ps = mDisabledSysPackages.get(name);
6665 return ps;
6666 }
6667 }
6668
6669 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
6670 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
6671 if (Config.LOGV) {
6672 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
6673 + " componentName = " + componentInfo.name);
6674 Log.v(TAG, "enabledComponents: "
6675 + Arrays.toString(packageSettings.enabledComponents.toArray()));
6676 Log.v(TAG, "disabledComponents: "
6677 + Arrays.toString(packageSettings.disabledComponents.toArray()));
6678 }
6679 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
6680 || ((componentInfo.enabled
6681 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
6682 || (componentInfo.applicationInfo.enabled
6683 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
6684 && !packageSettings.disabledComponents.contains(componentInfo.name))
6685 || packageSettings.enabledComponents.contains(componentInfo.name));
6686 }
6687 }
6688}