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