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