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