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