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