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