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