blob: 04e0253a02eec475717892126d407efab5afde20 [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 =
Mihai Preda074edef2009-05-18 17:13:31 +02001273 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1275 if (prefs != null && prefs.size() > 0) {
1276 // First figure out how good the original match set is.
1277 // We will only allow preferred activities that came
1278 // from the same match quality.
1279 int match = 0;
1280 final int N = query.size();
1281 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1282 for (int j=0; j<N; j++) {
1283 ResolveInfo ri = query.get(j);
1284 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1285 + ": 0x" + Integer.toHexString(match));
1286 if (ri.match > match) match = ri.match;
1287 }
1288 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1289 + Integer.toHexString(match));
1290 match &= IntentFilter.MATCH_CATEGORY_MASK;
1291 final int M = prefs.size();
1292 for (int i=0; i<M; i++) {
1293 PreferredActivity pa = prefs.get(i);
1294 if (pa.mMatch != match) {
1295 continue;
1296 }
1297 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1298 if (DEBUG_PREFERRED) {
1299 Log.v(TAG, "Got preferred activity:");
1300 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1301 }
1302 if (ai != null) {
1303 for (int j=0; j<N; j++) {
1304 ResolveInfo ri = query.get(j);
1305 if (!ri.activityInfo.applicationInfo.packageName
1306 .equals(ai.applicationInfo.packageName)) {
1307 continue;
1308 }
1309 if (!ri.activityInfo.name.equals(ai.name)) {
1310 continue;
1311 }
1312
1313 // Okay we found a previously set preferred app.
1314 // If the result set is different from when this
1315 // was created, we need to clear it and re-ask the
1316 // user their preference.
1317 if (!pa.sameSet(query, priority)) {
1318 Log.i(TAG, "Result set changed, dropping preferred activity for "
1319 + intent + " type " + resolvedType);
1320 mSettings.mPreferredActivities.removeFilter(pa);
1321 return null;
1322 }
1323
1324 // Yay!
1325 return ri;
1326 }
1327 }
1328 }
1329 }
1330 }
1331 return null;
1332 }
1333
1334 public List<ResolveInfo> queryIntentActivities(Intent intent,
1335 String resolvedType, int flags) {
1336 ComponentName comp = intent.getComponent();
1337 if (comp != null) {
1338 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1339 ActivityInfo ai = getActivityInfo(comp, flags);
1340 if (ai != null) {
1341 ResolveInfo ri = new ResolveInfo();
1342 ri.activityInfo = ai;
1343 list.add(ri);
1344 }
1345 return list;
1346 }
1347
1348 synchronized (mPackages) {
1349 return (List<ResolveInfo>)mActivities.
Mihai Preda074edef2009-05-18 17:13:31 +02001350 queryIntent(intent, resolvedType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 }
1352 }
1353
1354 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1355 Intent[] specifics, String[] specificTypes, Intent intent,
1356 String resolvedType, int flags) {
1357 final String resultsAction = intent.getAction();
1358
1359 List<ResolveInfo> results = queryIntentActivities(
1360 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1361 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1362
1363 int specificsPos = 0;
1364 int N;
1365
1366 // todo: note that the algorithm used here is O(N^2). This
1367 // isn't a problem in our current environment, but if we start running
1368 // into situations where we have more than 5 or 10 matches then this
1369 // should probably be changed to something smarter...
1370
1371 // First we go through and resolve each of the specific items
1372 // that were supplied, taking care of removing any corresponding
1373 // duplicate items in the generic resolve list.
1374 if (specifics != null) {
1375 for (int i=0; i<specifics.length; i++) {
1376 final Intent sintent = specifics[i];
1377 if (sintent == null) {
1378 continue;
1379 }
1380
1381 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1382 String action = sintent.getAction();
1383 if (resultsAction != null && resultsAction.equals(action)) {
1384 // If this action was explicitly requested, then don't
1385 // remove things that have it.
1386 action = null;
1387 }
1388 ComponentName comp = sintent.getComponent();
1389 ResolveInfo ri = null;
1390 ActivityInfo ai = null;
1391 if (comp == null) {
1392 ri = resolveIntent(
1393 sintent,
1394 specificTypes != null ? specificTypes[i] : null,
1395 flags);
1396 if (ri == null) {
1397 continue;
1398 }
1399 if (ri == mResolveInfo) {
1400 // ACK! Must do something better with this.
1401 }
1402 ai = ri.activityInfo;
1403 comp = new ComponentName(ai.applicationInfo.packageName,
1404 ai.name);
1405 } else {
1406 ai = getActivityInfo(comp, flags);
1407 if (ai == null) {
1408 continue;
1409 }
1410 }
1411
1412 // Look for any generic query activities that are duplicates
1413 // of this specific one, and remove them from the results.
1414 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1415 N = results.size();
1416 int j;
1417 for (j=specificsPos; j<N; j++) {
1418 ResolveInfo sri = results.get(j);
1419 if ((sri.activityInfo.name.equals(comp.getClassName())
1420 && sri.activityInfo.applicationInfo.packageName.equals(
1421 comp.getPackageName()))
1422 || (action != null && sri.filter.matchAction(action))) {
1423 results.remove(j);
1424 if (Config.LOGV) Log.v(
1425 TAG, "Removing duplicate item from " + j
1426 + " due to specific " + specificsPos);
1427 if (ri == null) {
1428 ri = sri;
1429 }
1430 j--;
1431 N--;
1432 }
1433 }
1434
1435 // Add this specific item to its proper place.
1436 if (ri == null) {
1437 ri = new ResolveInfo();
1438 ri.activityInfo = ai;
1439 }
1440 results.add(specificsPos, ri);
1441 ri.specificIndex = i;
1442 specificsPos++;
1443 }
1444 }
1445
1446 // Now we go through the remaining generic results and remove any
1447 // duplicate actions that are found here.
1448 N = results.size();
1449 for (int i=specificsPos; i<N-1; i++) {
1450 final ResolveInfo rii = results.get(i);
1451 if (rii.filter == null) {
1452 continue;
1453 }
1454
1455 // Iterate over all of the actions of this result's intent
1456 // filter... typically this should be just one.
1457 final Iterator<String> it = rii.filter.actionsIterator();
1458 if (it == null) {
1459 continue;
1460 }
1461 while (it.hasNext()) {
1462 final String action = it.next();
1463 if (resultsAction != null && resultsAction.equals(action)) {
1464 // If this action was explicitly requested, then don't
1465 // remove things that have it.
1466 continue;
1467 }
1468 for (int j=i+1; j<N; j++) {
1469 final ResolveInfo rij = results.get(j);
1470 if (rij.filter != null && rij.filter.hasAction(action)) {
1471 results.remove(j);
1472 if (Config.LOGV) Log.v(
1473 TAG, "Removing duplicate item from " + j
1474 + " due to action " + action + " at " + i);
1475 j--;
1476 N--;
1477 }
1478 }
1479 }
1480
1481 // If the caller didn't request filter information, drop it now
1482 // so we don't have to marshall/unmarshall it.
1483 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1484 rii.filter = null;
1485 }
1486 }
1487
1488 // Filter out the caller activity if so requested.
1489 if (caller != null) {
1490 N = results.size();
1491 for (int i=0; i<N; i++) {
1492 ActivityInfo ainfo = results.get(i).activityInfo;
1493 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1494 && caller.getClassName().equals(ainfo.name)) {
1495 results.remove(i);
1496 break;
1497 }
1498 }
1499 }
1500
1501 // If the caller didn't request filter information,
1502 // drop them now so we don't have to
1503 // marshall/unmarshall it.
1504 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1505 N = results.size();
1506 for (int i=0; i<N; i++) {
1507 results.get(i).filter = null;
1508 }
1509 }
1510
1511 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1512 return results;
1513 }
1514
1515 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1516 String resolvedType, int flags) {
1517 synchronized (mPackages) {
1518 return (List<ResolveInfo>)mReceivers.
Mihai Preda074edef2009-05-18 17:13:31 +02001519 queryIntent(intent, resolvedType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
1521 }
1522
1523 public ResolveInfo resolveService(Intent intent, String resolvedType,
1524 int flags) {
1525 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1526 flags);
1527 if (query != null) {
1528 if (query.size() >= 1) {
1529 // If there is more than one service with the same priority,
1530 // just arbitrarily pick the first one.
1531 return query.get(0);
1532 }
1533 }
1534 return null;
1535 }
1536
1537 public List<ResolveInfo> queryIntentServices(Intent intent,
1538 String resolvedType, int flags) {
1539 ComponentName comp = intent.getComponent();
1540 if (comp != null) {
1541 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1542 ServiceInfo si = getServiceInfo(comp, flags);
1543 if (si != null) {
1544 ResolveInfo ri = new ResolveInfo();
1545 ri.serviceInfo = si;
1546 list.add(ri);
1547 }
1548 return list;
1549 }
1550
1551 synchronized (mPackages) {
Mihai Preda074edef2009-05-18 17:13:31 +02001552 return (List<ResolveInfo>)mServices.queryIntent(intent, resolvedType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 }
1554 }
1555
1556 public List<PackageInfo> getInstalledPackages(int flags) {
1557 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1558
1559 synchronized (mPackages) {
1560 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1561 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1562 while (i.hasNext()) {
1563 final PackageSetting ps = i.next();
1564 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1565 if(psPkg != null) {
1566 finalList.add(psPkg);
1567 }
1568 }
1569 }
1570 else {
1571 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1572 while (i.hasNext()) {
1573 final PackageParser.Package p = i.next();
1574 if (p.applicationInfo != null) {
1575 PackageInfo pi = generatePackageInfo(p, flags);
1576 if(pi != null) {
1577 finalList.add(pi);
1578 }
1579 }
1580 }
1581 }
1582 }
1583 return finalList;
1584 }
1585
1586 public List<ApplicationInfo> getInstalledApplications(int flags) {
1587 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1588 synchronized(mPackages) {
1589 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1590 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1591 while (i.hasNext()) {
1592 final PackageSetting ps = i.next();
1593 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1594 if(ai != null) {
1595 finalList.add(ai);
1596 }
1597 }
1598 }
1599 else {
1600 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1601 while (i.hasNext()) {
1602 final PackageParser.Package p = i.next();
1603 if (p.applicationInfo != null) {
1604 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1605 if(ai != null) {
1606 finalList.add(ai);
1607 }
1608 }
1609 }
1610 }
1611 }
1612 return finalList;
1613 }
1614
1615 public List<ApplicationInfo> getPersistentApplications(int flags) {
1616 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1617
1618 synchronized (mPackages) {
1619 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1620 while (i.hasNext()) {
1621 PackageParser.Package p = i.next();
1622 if (p.applicationInfo != null
1623 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1624 && (!mSafeMode || (p.applicationInfo.flags
1625 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1626 finalList.add(p.applicationInfo);
1627 }
1628 }
1629 }
1630
1631 return finalList;
1632 }
1633
1634 public ProviderInfo resolveContentProvider(String name, int flags) {
1635 synchronized (mPackages) {
1636 final PackageParser.Provider provider = mProviders.get(name);
1637 return provider != null
1638 && mSettings.isEnabledLP(provider.info, flags)
1639 && (!mSafeMode || (provider.info.applicationInfo.flags
1640 &ApplicationInfo.FLAG_SYSTEM) != 0)
1641 ? PackageParser.generateProviderInfo(provider, flags)
1642 : null;
1643 }
1644 }
1645
1646 public void querySyncProviders(List outNames, List outInfo) {
1647 synchronized (mPackages) {
1648 Iterator<Map.Entry<String, PackageParser.Provider>> i
1649 = mProviders.entrySet().iterator();
1650
1651 while (i.hasNext()) {
1652 Map.Entry<String, PackageParser.Provider> entry = i.next();
1653 PackageParser.Provider p = entry.getValue();
1654
1655 if (p.syncable
1656 && (!mSafeMode || (p.info.applicationInfo.flags
1657 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1658 outNames.add(entry.getKey());
1659 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1660 }
1661 }
1662 }
1663 }
1664
1665 public List<ProviderInfo> queryContentProviders(String processName,
1666 int uid, int flags) {
1667 ArrayList<ProviderInfo> finalList = null;
1668
1669 synchronized (mPackages) {
1670 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1671 while (i.hasNext()) {
1672 PackageParser.Provider p = i.next();
1673 if (p.info.authority != null
1674 && (processName == null ||
1675 (p.info.processName.equals(processName)
1676 && p.info.applicationInfo.uid == uid))
1677 && mSettings.isEnabledLP(p.info, flags)
1678 && (!mSafeMode || (p.info.applicationInfo.flags
1679 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1680 if (finalList == null) {
1681 finalList = new ArrayList<ProviderInfo>(3);
1682 }
1683 finalList.add(PackageParser.generateProviderInfo(p,
1684 flags));
1685 }
1686 }
1687 }
1688
1689 if (finalList != null) {
1690 Collections.sort(finalList, mProviderInitOrderSorter);
1691 }
1692
1693 return finalList;
1694 }
1695
1696 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1697 int flags) {
1698 synchronized (mPackages) {
1699 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1700 return PackageParser.generateInstrumentationInfo(i, flags);
1701 }
1702 }
1703
1704 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1705 int flags) {
1706 ArrayList<InstrumentationInfo> finalList =
1707 new ArrayList<InstrumentationInfo>();
1708
1709 synchronized (mPackages) {
1710 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1711 while (i.hasNext()) {
1712 PackageParser.Instrumentation p = i.next();
1713 if (targetPackage == null
1714 || targetPackage.equals(p.info.targetPackage)) {
1715 finalList.add(PackageParser.generateInstrumentationInfo(p,
1716 flags));
1717 }
1718 }
1719 }
1720
1721 return finalList;
1722 }
1723
1724 private void scanDirLI(File dir, int flags, int scanMode) {
1725 Log.d(TAG, "Scanning app dir " + dir);
1726
1727 String[] files = dir.list();
1728
1729 int i;
1730 for (i=0; i<files.length; i++) {
1731 File file = new File(dir, files[i]);
1732 PackageParser.Package pkg = scanPackageLI(file, file, file,
1733 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1734 }
1735 }
1736
1737 private static void reportSettingsProblem(int priority, String msg) {
1738 try {
1739 File dataDir = Environment.getDataDirectory();
1740 File systemDir = new File(dataDir, "system");
1741 File fname = new File(systemDir, "uiderrors.txt");
1742 FileOutputStream out = new FileOutputStream(fname, true);
1743 PrintWriter pw = new PrintWriter(out);
1744 pw.println(msg);
1745 pw.close();
1746 FileUtils.setPermissions(
1747 fname.toString(),
1748 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1749 -1, -1);
1750 } catch (java.io.IOException e) {
1751 }
1752 Log.println(priority, TAG, msg);
1753 }
1754
1755 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1756 PackageParser.Package pkg, File srcFile, int parseFlags) {
1757 if (GET_CERTIFICATES) {
1758 if (ps == null || !ps.codePath.equals(srcFile)
1759 || ps.getTimeStamp() != srcFile.lastModified()) {
1760 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1761 if (!pp.collectCertificates(pkg, parseFlags)) {
1762 mLastScanError = pp.getParseError();
1763 return false;
1764 }
1765 }
1766 }
1767 return true;
1768 }
1769
1770 /*
1771 * Scan a package and return the newly parsed package.
1772 * Returns null in case of errors and the error code is stored in mLastScanError
1773 */
1774 private PackageParser.Package scanPackageLI(File scanFile,
1775 File destCodeFile, File destResourceFile, int parseFlags,
1776 int scanMode) {
1777 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1778 parseFlags |= mDefParseFlags;
1779 PackageParser pp = new PackageParser(scanFile.getPath());
1780 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07001781 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 final PackageParser.Package pkg = pp.parsePackage(scanFile,
1783 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
1784 if (pkg == null) {
1785 mLastScanError = pp.getParseError();
1786 return null;
1787 }
1788 PackageSetting ps;
1789 PackageSetting updatedPkg;
1790 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001791 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
1793 }
1794 if (updatedPkg != null) {
1795 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
1796 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
1797 }
1798 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1799 // Check for updated system applications here
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001800 if (updatedPkg != null) {
1801 if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
1802 if (pkg.mVersionCode <= ps.versionCode) {
1803 // The system package has been updated and the code path does not match
1804 // Ignore entry. Just return
1805 Log.w(TAG, "Package:" + pkg.packageName +
1806 " has been updated. Ignoring the one from path:"+scanFile);
1807 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1808 return null;
1809 } else {
1810 // Delete the older apk pointed to by ps
1811 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
1812 mSettings.enableSystemPackageLP(ps.name);
1813 }
1814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 }
1816 }
1817 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
1818 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
1819 return null;
1820 }
1821 // The apk is forward locked (not public) if its code and resources
1822 // are kept in different files.
1823 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
1824 scanMode |= SCAN_FORWARD_LOCKED;
1825 }
1826 // Note that we invoke the following method only if we are about to unpack an application
1827 return scanPackageLI(scanFile, destCodeFile, destResourceFile,
1828 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
1829 }
1830
1831 private static String fixProcessName(String defProcessName,
1832 String processName, int uid) {
1833 if (processName == null) {
1834 return defProcessName;
1835 }
1836 return processName;
1837 }
1838
1839 private boolean verifySignaturesLP(PackageSetting pkgSetting,
1840 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
1841 if (pkg.mSignatures != null) {
1842 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
1843 updateSignature)) {
1844 Log.e(TAG, "Package " + pkg.packageName
1845 + " signatures do not match the previously installed version; ignoring!");
1846 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1847 return false;
1848 }
1849
1850 if (pkgSetting.sharedUser != null) {
1851 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1852 pkg.mSignatures, updateSignature)) {
1853 Log.e(TAG, "Package " + pkg.packageName
1854 + " has no signatures that match those in shared user "
1855 + pkgSetting.sharedUser.name + "; ignoring!");
1856 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
1857 return false;
1858 }
1859 }
1860 } else {
1861 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1862 }
1863 return true;
1864 }
1865
1866 private PackageParser.Package scanPackageLI(
1867 File scanFile, File destCodeFile, File destResourceFile,
1868 PackageParser.Package pkg, int parseFlags, int scanMode) {
1869
1870 mScanningPath = scanFile;
1871 if (pkg == null) {
1872 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1873 return null;
1874 }
1875
1876 final String pkgName = pkg.applicationInfo.packageName;
1877 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1878 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
1879 }
1880
1881 if (pkgName.equals("android")) {
1882 synchronized (mPackages) {
1883 if (mAndroidApplication != null) {
1884 Log.w(TAG, "*************************************************");
1885 Log.w(TAG, "Core android package being redefined. Skipping.");
1886 Log.w(TAG, " file=" + mScanningPath);
1887 Log.w(TAG, "*************************************************");
1888 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1889 return null;
1890 }
1891
1892 // Set up information for our fall-back user intent resolution
1893 // activity.
1894 mPlatformPackage = pkg;
1895 pkg.mVersionCode = mSdkVersion;
1896 mAndroidApplication = pkg.applicationInfo;
1897 mResolveActivity.applicationInfo = mAndroidApplication;
1898 mResolveActivity.name = ResolverActivity.class.getName();
1899 mResolveActivity.packageName = mAndroidApplication.packageName;
1900 mResolveActivity.processName = mAndroidApplication.processName;
1901 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1902 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1903 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
1904 mResolveActivity.exported = true;
1905 mResolveActivity.enabled = true;
1906 mResolveInfo.activityInfo = mResolveActivity;
1907 mResolveInfo.priority = 0;
1908 mResolveInfo.preferredOrder = 0;
1909 mResolveInfo.match = 0;
1910 mResolveComponentName = new ComponentName(
1911 mAndroidApplication.packageName, mResolveActivity.name);
1912 }
1913 }
1914
1915 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
1916 TAG, "Scanning package " + pkgName);
1917 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
1918 Log.w(TAG, "*************************************************");
1919 Log.w(TAG, "Application package " + pkgName
1920 + " already installed. Skipping duplicate.");
1921 Log.w(TAG, "*************************************************");
1922 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1923 return null;
1924 }
1925
1926 SharedUserSetting suid = null;
1927 PackageSetting pkgSetting = null;
1928
1929 boolean removeExisting = false;
1930
1931 synchronized (mPackages) {
1932 // Check all shared libraries and map to their actual file path.
1933 if (pkg.usesLibraryFiles != null) {
1934 for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
1935 String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
1936 if (file == null) {
1937 Log.e(TAG, "Package " + pkg.packageName
1938 + " requires unavailable shared library "
1939 + pkg.usesLibraryFiles[i] + "; ignoring!");
1940 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
1941 return null;
1942 }
1943 pkg.usesLibraryFiles[i] = file;
1944 }
1945 }
1946
1947 if (pkg.mSharedUserId != null) {
1948 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
1949 pkg.applicationInfo.flags, true);
1950 if (suid == null) {
1951 Log.w(TAG, "Creating application package " + pkgName
1952 + " for shared user failed");
1953 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1954 return null;
1955 }
1956 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
1957 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
1958 + suid.userId + "): packages=" + suid.packages);
1959 }
1960 }
1961
1962 // Just create the setting, don't add it yet
1963 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
1964 destResourceFile, pkg.applicationInfo.flags, true, false);
1965 if (pkgSetting == null) {
1966 Log.w(TAG, "Creating application package " + pkgName + " failed");
1967 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1968 return null;
1969 }
1970 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
1971 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
1972 }
1973
1974 pkg.applicationInfo.uid = pkgSetting.userId;
1975 pkg.mExtras = pkgSetting;
1976
1977 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
1978 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
1979 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
1980 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1981 return null;
1982 }
1983 // The signature has changed, but this package is in the system
1984 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07001985 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 // However... if this package is part of a shared user, but it
1987 // doesn't match the signature of the shared user, let's fail.
1988 // What this means is that you can't change the signatures
1989 // associated with an overall shared user, which doesn't seem all
1990 // that unreasonable.
1991 if (pkgSetting.sharedUser != null) {
1992 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1993 pkg.mSignatures, false)) {
1994 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
1995 return null;
1996 }
1997 }
1998 removeExisting = true;
1999 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002000
2001 // Verify that this new package doesn't have any content providers
2002 // that conflict with existing packages. Only do this if the
2003 // package isn't already installed, since we don't want to break
2004 // things that are installed.
2005 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2006 int N = pkg.providers.size();
2007 int i;
2008 for (i=0; i<N; i++) {
2009 PackageParser.Provider p = pkg.providers.get(i);
2010 String names[] = p.info.authority.split(";");
2011 for (int j = 0; j < names.length; j++) {
2012 if (mProviders.containsKey(names[j])) {
2013 PackageParser.Provider other = mProviders.get(names[j]);
2014 Log.w(TAG, "Can't install because provider name " + names[j] +
2015 " (in package " + pkg.applicationInfo.packageName +
2016 ") is already used by "
2017 + ((other != null && other.component != null)
2018 ? other.component.getPackageName() : "?"));
2019 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2020 return null;
2021 }
2022 }
2023 }
2024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 }
2026
2027 if (removeExisting) {
2028 if (mInstaller != null) {
2029 int ret = mInstaller.remove(pkgName);
2030 if (ret != 0) {
2031 String msg = "System package " + pkg.packageName
2032 + " could not have data directory erased after signature change.";
2033 reportSettingsProblem(Log.WARN, msg);
2034 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2035 return null;
2036 }
2037 }
2038 Log.w(TAG, "System package " + pkg.packageName
2039 + " signature changed: existing data removed.");
2040 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2041 }
2042
2043 long scanFileTime = scanFile.lastModified();
2044 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2045 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2046 pkg.applicationInfo.processName = fixProcessName(
2047 pkg.applicationInfo.packageName,
2048 pkg.applicationInfo.processName,
2049 pkg.applicationInfo.uid);
2050 pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
2051
2052 File dataPath;
2053 if (mPlatformPackage == pkg) {
2054 // The system package is special.
2055 dataPath = new File (Environment.getDataDirectory(), "system");
2056 pkg.applicationInfo.dataDir = dataPath.getPath();
2057 } else {
2058 // This is a normal package, need to make its data directory.
2059 dataPath = new File(mAppDataDir, pkgName);
2060 if (dataPath.exists()) {
2061 mOutPermissions[1] = 0;
2062 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2063 if (mOutPermissions[1] == pkg.applicationInfo.uid
2064 || !Process.supportsProcesses()) {
2065 pkg.applicationInfo.dataDir = dataPath.getPath();
2066 } else {
2067 boolean recovered = false;
2068 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2069 // If this is a system app, we can at least delete its
2070 // current data so the application will still work.
2071 if (mInstaller != null) {
2072 int ret = mInstaller.remove(pkgName);
2073 if(ret >= 0) {
2074 // Old data gone!
2075 String msg = "System package " + pkg.packageName
2076 + " has changed from uid: "
2077 + mOutPermissions[1] + " to "
2078 + pkg.applicationInfo.uid + "; old data erased";
2079 reportSettingsProblem(Log.WARN, msg);
2080 recovered = true;
2081
2082 // And now re-install the app.
2083 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2084 pkg.applicationInfo.uid);
2085 if (ret == -1) {
2086 // Ack should not happen!
2087 msg = "System package " + pkg.packageName
2088 + " could not have data directory re-created after delete.";
2089 reportSettingsProblem(Log.WARN, msg);
2090 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2091 return null;
2092 }
2093 }
2094 }
2095 if (!recovered) {
2096 mHasSystemUidErrors = true;
2097 }
2098 }
2099 if (!recovered) {
2100 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2101 + pkg.applicationInfo.uid + "/fs_"
2102 + mOutPermissions[1];
2103 String msg = "Package " + pkg.packageName
2104 + " has mismatched uid: "
2105 + mOutPermissions[1] + " on disk, "
2106 + pkg.applicationInfo.uid + " in settings";
2107 synchronized (mPackages) {
2108 if (!mReportedUidError) {
2109 mReportedUidError = true;
2110 msg = msg + "; read messages:\n"
2111 + mSettings.getReadMessagesLP();
2112 }
2113 reportSettingsProblem(Log.ERROR, msg);
2114 }
2115 }
2116 }
2117 pkg.applicationInfo.dataDir = dataPath.getPath();
2118 } else {
2119 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2120 Log.v(TAG, "Want this data dir: " + dataPath);
2121 //invoke installer to do the actual installation
2122 if (mInstaller != null) {
2123 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2124 pkg.applicationInfo.uid);
2125 if(ret < 0) {
2126 // Error from installer
2127 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2128 return null;
2129 }
2130 } else {
2131 dataPath.mkdirs();
2132 if (dataPath.exists()) {
2133 FileUtils.setPermissions(
2134 dataPath.toString(),
2135 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2136 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2137 }
2138 }
2139 if (dataPath.exists()) {
2140 pkg.applicationInfo.dataDir = dataPath.getPath();
2141 } else {
2142 Log.w(TAG, "Unable to create data directory: " + dataPath);
2143 pkg.applicationInfo.dataDir = null;
2144 }
2145 }
2146 }
2147
2148 // Perform shared library installation and dex validation and
2149 // optimization, if this is not a system app.
2150 if (mInstaller != null) {
2151 String path = scanFile.getPath();
2152 if (scanFileNewer) {
2153 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002154 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2155 if (err != PackageManager.INSTALL_SUCCEEDED) {
2156 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 return null;
2158 }
2159 }
2160
2161 if ((scanMode&SCAN_NO_DEX) == 0
2162 && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
2163 int ret = 0;
2164 try {
2165 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2166 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2167 (scanMode&SCAN_FORWARD_LOCKED) == 0);
2168 }
2169 } catch (FileNotFoundException e) {
2170 Log.w(TAG, "Apk not found for dexopt: " + path);
2171 ret = -1;
2172 } catch (IOException e) {
2173 Log.w(TAG, "Exception reading apk: " + path, e);
2174 ret = -1;
2175 }
2176 if (ret < 0) {
2177 //error from installer
2178 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2179 return null;
2180 }
2181 }
2182 }
2183
2184 if (mFactoryTest && pkg.requestedPermissions.contains(
2185 android.Manifest.permission.FACTORY_TEST)) {
2186 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2187 }
2188
2189 if ((scanMode&SCAN_MONITOR) != 0) {
2190 pkg.mPath = destCodeFile.getAbsolutePath();
2191 mAppDirs.put(pkg.mPath, pkg);
2192 }
2193
2194 synchronized (mPackages) {
2195 // We don't expect installation to fail beyond this point
2196 // Add the new setting to mSettings
2197 mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
2198 // Add the new setting to mPackages
2199 mPackages.put(pkg.applicationInfo.packageName, pkg);
2200 int N = pkg.providers.size();
2201 StringBuilder r = null;
2202 int i;
2203 for (i=0; i<N; i++) {
2204 PackageParser.Provider p = pkg.providers.get(i);
2205 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2206 p.info.processName, pkg.applicationInfo.uid);
2207 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2208 p.info.name), p);
2209 p.syncable = p.info.isSyncable;
2210 String names[] = p.info.authority.split(";");
2211 p.info.authority = null;
2212 for (int j = 0; j < names.length; j++) {
2213 if (j == 1 && p.syncable) {
2214 // We only want the first authority for a provider to possibly be
2215 // syncable, so if we already added this provider using a different
2216 // authority clear the syncable flag. We copy the provider before
2217 // changing it because the mProviders object contains a reference
2218 // to a provider that we don't want to change.
2219 // Only do this for the second authority since the resulting provider
2220 // object can be the same for all future authorities for this provider.
2221 p = new PackageParser.Provider(p);
2222 p.syncable = false;
2223 }
2224 if (!mProviders.containsKey(names[j])) {
2225 mProviders.put(names[j], p);
2226 if (p.info.authority == null) {
2227 p.info.authority = names[j];
2228 } else {
2229 p.info.authority = p.info.authority + ";" + names[j];
2230 }
2231 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2232 Log.d(TAG, "Registered content provider: " + names[j] +
2233 ", className = " + p.info.name +
2234 ", isSyncable = " + p.info.isSyncable);
2235 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002236 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 Log.w(TAG, "Skipping provider name " + names[j] +
2238 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002239 "): name already used by "
2240 + ((other != null && other.component != null)
2241 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 }
2243 }
2244 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2245 if (r == null) {
2246 r = new StringBuilder(256);
2247 } else {
2248 r.append(' ');
2249 }
2250 r.append(p.info.name);
2251 }
2252 }
2253 if (r != null) {
2254 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2255 }
2256
2257 N = pkg.services.size();
2258 r = null;
2259 for (i=0; i<N; i++) {
2260 PackageParser.Service s = pkg.services.get(i);
2261 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2262 s.info.processName, pkg.applicationInfo.uid);
2263 mServices.addService(s);
2264 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2265 if (r == null) {
2266 r = new StringBuilder(256);
2267 } else {
2268 r.append(' ');
2269 }
2270 r.append(s.info.name);
2271 }
2272 }
2273 if (r != null) {
2274 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2275 }
2276
2277 N = pkg.receivers.size();
2278 r = null;
2279 for (i=0; i<N; i++) {
2280 PackageParser.Activity a = pkg.receivers.get(i);
2281 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2282 a.info.processName, pkg.applicationInfo.uid);
2283 mReceivers.addActivity(a, "receiver");
2284 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2285 if (r == null) {
2286 r = new StringBuilder(256);
2287 } else {
2288 r.append(' ');
2289 }
2290 r.append(a.info.name);
2291 }
2292 }
2293 if (r != null) {
2294 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2295 }
2296
2297 N = pkg.activities.size();
2298 r = null;
2299 for (i=0; i<N; i++) {
2300 PackageParser.Activity a = pkg.activities.get(i);
2301 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2302 a.info.processName, pkg.applicationInfo.uid);
2303 mActivities.addActivity(a, "activity");
2304 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2305 if (r == null) {
2306 r = new StringBuilder(256);
2307 } else {
2308 r.append(' ');
2309 }
2310 r.append(a.info.name);
2311 }
2312 }
2313 if (r != null) {
2314 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2315 }
2316
2317 N = pkg.permissionGroups.size();
2318 r = null;
2319 for (i=0; i<N; i++) {
2320 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2321 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2322 if (cur == null) {
2323 mPermissionGroups.put(pg.info.name, pg);
2324 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2325 if (r == null) {
2326 r = new StringBuilder(256);
2327 } else {
2328 r.append(' ');
2329 }
2330 r.append(pg.info.name);
2331 }
2332 } else {
2333 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2334 + pg.info.packageName + " ignored: original from "
2335 + cur.info.packageName);
2336 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2337 if (r == null) {
2338 r = new StringBuilder(256);
2339 } else {
2340 r.append(' ');
2341 }
2342 r.append("DUP:");
2343 r.append(pg.info.name);
2344 }
2345 }
2346 }
2347 if (r != null) {
2348 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2349 }
2350
2351 N = pkg.permissions.size();
2352 r = null;
2353 for (i=0; i<N; i++) {
2354 PackageParser.Permission p = pkg.permissions.get(i);
2355 HashMap<String, BasePermission> permissionMap =
2356 p.tree ? mSettings.mPermissionTrees
2357 : mSettings.mPermissions;
2358 p.group = mPermissionGroups.get(p.info.group);
2359 if (p.info.group == null || p.group != null) {
2360 BasePermission bp = permissionMap.get(p.info.name);
2361 if (bp == null) {
2362 bp = new BasePermission(p.info.name, p.info.packageName,
2363 BasePermission.TYPE_NORMAL);
2364 permissionMap.put(p.info.name, bp);
2365 }
2366 if (bp.perm == null) {
2367 if (bp.sourcePackage == null
2368 || bp.sourcePackage.equals(p.info.packageName)) {
2369 BasePermission tree = findPermissionTreeLP(p.info.name);
2370 if (tree == null
2371 || tree.sourcePackage.equals(p.info.packageName)) {
2372 bp.perm = p;
2373 bp.uid = pkg.applicationInfo.uid;
2374 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2375 if (r == null) {
2376 r = new StringBuilder(256);
2377 } else {
2378 r.append(' ');
2379 }
2380 r.append(p.info.name);
2381 }
2382 } else {
2383 Log.w(TAG, "Permission " + p.info.name + " from package "
2384 + p.info.packageName + " ignored: base tree "
2385 + tree.name + " is from package "
2386 + tree.sourcePackage);
2387 }
2388 } else {
2389 Log.w(TAG, "Permission " + p.info.name + " from package "
2390 + p.info.packageName + " ignored: original from "
2391 + bp.sourcePackage);
2392 }
2393 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2394 if (r == null) {
2395 r = new StringBuilder(256);
2396 } else {
2397 r.append(' ');
2398 }
2399 r.append("DUP:");
2400 r.append(p.info.name);
2401 }
2402 } else {
2403 Log.w(TAG, "Permission " + p.info.name + " from package "
2404 + p.info.packageName + " ignored: no group "
2405 + p.group);
2406 }
2407 }
2408 if (r != null) {
2409 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2410 }
2411
2412 N = pkg.instrumentation.size();
2413 r = null;
2414 for (i=0; i<N; i++) {
2415 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2416 a.info.packageName = pkg.applicationInfo.packageName;
2417 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2418 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2419 a.info.dataDir = pkg.applicationInfo.dataDir;
2420 mInstrumentation.put(a.component, a);
2421 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2422 if (r == null) {
2423 r = new StringBuilder(256);
2424 } else {
2425 r.append(' ');
2426 }
2427 r.append(a.info.name);
2428 }
2429 }
2430 if (r != null) {
2431 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2432 }
2433
2434 pkgSetting.setTimeStamp(scanFileTime);
2435 }
2436
2437 return pkg;
2438 }
2439
Dianne Hackbornb1811182009-05-21 15:45:42 -07002440 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2441 File dataPath, File scanFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002443 final String sharedLibraryABI = Build.CPU_ABI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2445 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2446 final String sharedLibrarySuffix = ".so";
Dianne Hackbornb1811182009-05-21 15:45:42 -07002447 boolean hasNativeCode = false;
2448 boolean installedNativeCode = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449 try {
2450 ZipFile zipFile = new ZipFile(scanFile);
2451 Enumeration<ZipEntry> entries =
2452 (Enumeration<ZipEntry>) zipFile.entries();
2453
2454 while (entries.hasMoreElements()) {
2455 ZipEntry entry = entries.nextElement();
2456 if (entry.isDirectory()) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002457 if (!hasNativeCode && entry.getName().startsWith("lib")) {
2458 hasNativeCode = true;
2459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 continue;
2461 }
2462 String entryName = entry.getName();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002463 if (entryName.startsWith("lib/")) {
2464 hasNativeCode = true;
2465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2467 && entryName.endsWith(sharedLibrarySuffix))) {
2468 continue;
2469 }
2470 String libFileName = entryName.substring(
2471 apkLibraryDirectory.length());
2472 if (libFileName.contains("/")
2473 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2474 continue;
2475 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002476
2477 installedNativeCode = true;
2478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2480 File.separator + libFileName;
2481 File sharedLibraryFile = new File(sharedLibraryFilePath);
2482 if (! sharedLibraryFile.exists() ||
2483 sharedLibraryFile.length() != entry.getSize() ||
2484 sharedLibraryFile.lastModified() != entry.getTime()) {
2485 if (Config.LOGD) {
2486 Log.d(TAG, "Caching shared lib " + entry.getName());
2487 }
2488 if (mInstaller == null) {
2489 sharedLibraryDir.mkdir();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 }
2491 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2492 sharedLibraryFile);
2493 }
2494 }
2495 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002496 Log.w(TAG, "Failed to cache package shared libs", e);
2497 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002499
2500 if (hasNativeCode && !installedNativeCode) {
2501 Log.w(TAG, "Install failed: .apk has native code but none for arch "
2502 + Build.CPU_ABI);
2503 return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
2504 }
2505
2506 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 }
2508
2509 private void cacheSharedLibLI(PackageParser.Package pkg,
2510 ZipFile zipFile, ZipEntry entry,
2511 File sharedLibraryDir,
2512 File sharedLibraryFile) throws IOException {
2513 InputStream inputStream = zipFile.getInputStream(entry);
2514 try {
2515 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2516 String tempFilePath = tempFile.getPath();
2517 // XXX package manager can't change owner, so the lib files for
2518 // now need to be left as world readable and owned by the system.
2519 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2520 ! tempFile.setLastModified(entry.getTime()) ||
2521 FileUtils.setPermissions(tempFilePath,
2522 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2523 |FileUtils.S_IROTH, -1, -1) != 0 ||
2524 ! tempFile.renameTo(sharedLibraryFile)) {
2525 // Failed to properly write file.
2526 tempFile.delete();
2527 throw new IOException("Couldn't create cached shared lib "
2528 + sharedLibraryFile + " in " + sharedLibraryDir);
2529 }
2530 } finally {
2531 inputStream.close();
2532 }
2533 }
2534
2535 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2536 if (chatty && Config.LOGD) Log.d(
2537 TAG, "Removing package " + pkg.applicationInfo.packageName );
2538
2539 synchronized (mPackages) {
2540 if (pkg.mPreferredOrder > 0) {
2541 mSettings.mPreferredPackages.remove(pkg);
2542 pkg.mPreferredOrder = 0;
2543 updatePreferredIndicesLP();
2544 }
2545
2546 clearPackagePreferredActivitiesLP(pkg.packageName);
2547
2548 mPackages.remove(pkg.applicationInfo.packageName);
2549 if (pkg.mPath != null) {
2550 mAppDirs.remove(pkg.mPath);
2551 }
2552
2553 PackageSetting ps = (PackageSetting)pkg.mExtras;
2554 if (ps != null && ps.sharedUser != null) {
2555 // XXX don't do this until the data is removed.
2556 if (false) {
2557 ps.sharedUser.packages.remove(ps);
2558 if (ps.sharedUser.packages.size() == 0) {
2559 // Remove.
2560 }
2561 }
2562 }
2563
2564 int N = pkg.providers.size();
2565 StringBuilder r = null;
2566 int i;
2567 for (i=0; i<N; i++) {
2568 PackageParser.Provider p = pkg.providers.get(i);
2569 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2570 p.info.name));
2571 if (p.info.authority == null) {
2572
2573 /* The is another ContentProvider with this authority when
2574 * this app was installed so this authority is null,
2575 * Ignore it as we don't have to unregister the provider.
2576 */
2577 continue;
2578 }
2579 String names[] = p.info.authority.split(";");
2580 for (int j = 0; j < names.length; j++) {
2581 if (mProviders.get(names[j]) == p) {
2582 mProviders.remove(names[j]);
2583 if (chatty && Config.LOGD) Log.d(
2584 TAG, "Unregistered content provider: " + names[j] +
2585 ", className = " + p.info.name +
2586 ", isSyncable = " + p.info.isSyncable);
2587 }
2588 }
2589 if (chatty) {
2590 if (r == null) {
2591 r = new StringBuilder(256);
2592 } else {
2593 r.append(' ');
2594 }
2595 r.append(p.info.name);
2596 }
2597 }
2598 if (r != null) {
2599 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2600 }
2601
2602 N = pkg.services.size();
2603 r = null;
2604 for (i=0; i<N; i++) {
2605 PackageParser.Service s = pkg.services.get(i);
2606 mServices.removeService(s);
2607 if (chatty) {
2608 if (r == null) {
2609 r = new StringBuilder(256);
2610 } else {
2611 r.append(' ');
2612 }
2613 r.append(s.info.name);
2614 }
2615 }
2616 if (r != null) {
2617 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2618 }
2619
2620 N = pkg.receivers.size();
2621 r = null;
2622 for (i=0; i<N; i++) {
2623 PackageParser.Activity a = pkg.receivers.get(i);
2624 mReceivers.removeActivity(a, "receiver");
2625 if (chatty) {
2626 if (r == null) {
2627 r = new StringBuilder(256);
2628 } else {
2629 r.append(' ');
2630 }
2631 r.append(a.info.name);
2632 }
2633 }
2634 if (r != null) {
2635 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2636 }
2637
2638 N = pkg.activities.size();
2639 r = null;
2640 for (i=0; i<N; i++) {
2641 PackageParser.Activity a = pkg.activities.get(i);
2642 mActivities.removeActivity(a, "activity");
2643 if (chatty) {
2644 if (r == null) {
2645 r = new StringBuilder(256);
2646 } else {
2647 r.append(' ');
2648 }
2649 r.append(a.info.name);
2650 }
2651 }
2652 if (r != null) {
2653 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2654 }
2655
2656 N = pkg.permissions.size();
2657 r = null;
2658 for (i=0; i<N; i++) {
2659 PackageParser.Permission p = pkg.permissions.get(i);
2660 boolean tree = false;
2661 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2662 if (bp == null) {
2663 tree = true;
2664 bp = mSettings.mPermissionTrees.get(p.info.name);
2665 }
2666 if (bp != null && bp.perm == p) {
2667 if (bp.type != BasePermission.TYPE_BUILTIN) {
2668 if (tree) {
2669 mSettings.mPermissionTrees.remove(p.info.name);
2670 } else {
2671 mSettings.mPermissions.remove(p.info.name);
2672 }
2673 } else {
2674 bp.perm = null;
2675 }
2676 if (chatty) {
2677 if (r == null) {
2678 r = new StringBuilder(256);
2679 } else {
2680 r.append(' ');
2681 }
2682 r.append(p.info.name);
2683 }
2684 }
2685 }
2686 if (r != null) {
2687 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2688 }
2689
2690 N = pkg.instrumentation.size();
2691 r = null;
2692 for (i=0; i<N; i++) {
2693 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2694 mInstrumentation.remove(a.component);
2695 if (chatty) {
2696 if (r == null) {
2697 r = new StringBuilder(256);
2698 } else {
2699 r.append(' ');
2700 }
2701 r.append(a.info.name);
2702 }
2703 }
2704 if (r != null) {
2705 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2706 }
2707 }
2708 }
2709
2710 private static final boolean isPackageFilename(String name) {
2711 return name != null && name.endsWith(".apk");
2712 }
2713
2714 private void updatePermissionsLP() {
2715 // Make sure there are no dangling permission trees.
2716 Iterator<BasePermission> it = mSettings.mPermissionTrees
2717 .values().iterator();
2718 while (it.hasNext()) {
2719 BasePermission bp = it.next();
2720 if (bp.perm == null) {
2721 Log.w(TAG, "Removing dangling permission tree: " + bp.name
2722 + " from package " + bp.sourcePackage);
2723 it.remove();
2724 }
2725 }
2726
2727 // Make sure all dynamic permissions have been assigned to a package,
2728 // and make sure there are no dangling permissions.
2729 it = mSettings.mPermissions.values().iterator();
2730 while (it.hasNext()) {
2731 BasePermission bp = it.next();
2732 if (bp.type == BasePermission.TYPE_DYNAMIC) {
2733 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
2734 + bp.name + " pkg=" + bp.sourcePackage
2735 + " info=" + bp.pendingInfo);
2736 if (bp.perm == null && bp.pendingInfo != null) {
2737 BasePermission tree = findPermissionTreeLP(bp.name);
2738 if (tree != null) {
2739 bp.perm = new PackageParser.Permission(tree.perm.owner,
2740 new PermissionInfo(bp.pendingInfo));
2741 bp.perm.info.packageName = tree.perm.info.packageName;
2742 bp.perm.info.name = bp.name;
2743 bp.uid = tree.uid;
2744 }
2745 }
2746 }
2747 if (bp.perm == null) {
2748 Log.w(TAG, "Removing dangling permission: " + bp.name
2749 + " from package " + bp.sourcePackage);
2750 it.remove();
2751 }
2752 }
2753
2754 // Now update the permissions for all packages, in particular
2755 // replace the granted permissions of the system packages.
2756 for (PackageParser.Package pkg : mPackages.values()) {
2757 grantPermissionsLP(pkg, false);
2758 }
2759 }
2760
2761 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
2762 final PackageSetting ps = (PackageSetting)pkg.mExtras;
2763 if (ps == null) {
2764 return;
2765 }
2766 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2767 boolean addedPermission = false;
2768
2769 if (replace) {
2770 ps.permissionsFixed = false;
2771 if (gp == ps) {
2772 gp.grantedPermissions.clear();
2773 gp.gids = mGlobalGids;
2774 }
2775 }
2776
2777 if (gp.gids == null) {
2778 gp.gids = mGlobalGids;
2779 }
2780
2781 final int N = pkg.requestedPermissions.size();
2782 for (int i=0; i<N; i++) {
2783 String name = pkg.requestedPermissions.get(i);
2784 BasePermission bp = mSettings.mPermissions.get(name);
2785 PackageParser.Permission p = bp != null ? bp.perm : null;
2786 if (false) {
2787 if (gp != ps) {
2788 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
2789 + ": " + p);
2790 }
2791 }
2792 if (p != null) {
2793 final String perm = p.info.name;
2794 boolean allowed;
2795 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
2796 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
2797 allowed = true;
2798 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
2799 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2800 allowed = (checkSignaturesLP(p.owner, pkg)
2801 == PackageManager.SIGNATURE_MATCH)
2802 || (checkSignaturesLP(mPlatformPackage, pkg)
2803 == PackageManager.SIGNATURE_MATCH);
2804 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2805 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
2806 // For updated system applications, the signatureOrSystem permission
2807 // is granted only if it had been defined by the original application.
2808 if ((pkg.applicationInfo.flags
2809 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
2810 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
2811 if(sysPs.grantedPermissions.contains(perm)) {
2812 allowed = true;
2813 } else {
2814 allowed = false;
2815 }
2816 } else {
2817 allowed = true;
2818 }
2819 }
2820 }
2821 } else {
2822 allowed = false;
2823 }
2824 if (false) {
2825 if (gp != ps) {
2826 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
2827 }
2828 }
2829 if (allowed) {
2830 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
2831 && ps.permissionsFixed) {
2832 // If this is an existing, non-system package, then
2833 // we can't add any new permissions to it.
2834 if (!gp.loadedPermissions.contains(perm)) {
2835 allowed = false;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002836 // Except... if this is a permission that was added
2837 // to the platform (note: need to only do this when
2838 // updating the platform).
2839 final int NP = PackageParser.NEW_PERMISSIONS.length;
2840 for (int ip=0; ip<NP; ip++) {
2841 final PackageParser.NewPermissionInfo npi
2842 = PackageParser.NEW_PERMISSIONS[ip];
2843 if (npi.name.equals(perm)
2844 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
2845 allowed = true;
2846 Log.i(TAG, "Auto-granting WRITE_SDCARD to old pkg "
2847 + pkg.packageName);
2848 break;
2849 }
2850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852 }
2853 if (allowed) {
2854 if (!gp.grantedPermissions.contains(perm)) {
2855 addedPermission = true;
2856 gp.grantedPermissions.add(perm);
2857 gp.gids = appendInts(gp.gids, bp.gids);
2858 }
2859 } else {
2860 Log.w(TAG, "Not granting permission " + perm
2861 + " to package " + pkg.packageName
2862 + " because it was previously installed without");
2863 }
2864 } else {
2865 Log.w(TAG, "Not granting permission " + perm
2866 + " to package " + pkg.packageName
2867 + " (protectionLevel=" + p.info.protectionLevel
2868 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
2869 + ")");
2870 }
2871 } else {
2872 Log.w(TAG, "Unknown permission " + name
2873 + " in package " + pkg.packageName);
2874 }
2875 }
2876
2877 if ((addedPermission || replace) && !ps.permissionsFixed &&
2878 (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2879 // This is the first that we have heard about this package, so the
2880 // permissions we have now selected are fixed until explicitly
2881 // changed.
2882 ps.permissionsFixed = true;
2883 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
2884 }
2885 }
2886
2887 private final class ActivityIntentResolver
2888 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02002889 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02002891 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
2893
Mihai Preda074edef2009-05-18 17:13:31 +02002894 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02002896 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2898 }
2899
Mihai Predaeae850c2009-05-13 10:13:48 +02002900 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
2901 ArrayList<PackageParser.Activity> packageActivities) {
2902 if (packageActivities == null) {
2903 return null;
2904 }
2905 mFlags = flags;
2906 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
2907 int N = packageActivities.size();
2908 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
2909 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02002910
2911 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02002912 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02002913 intentFilters = packageActivities.get(i).intents;
2914 if (intentFilters != null && intentFilters.size() > 0) {
2915 listCut.add(intentFilters);
2916 }
Mihai Predaeae850c2009-05-13 10:13:48 +02002917 }
2918 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
2919 }
2920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 public final void addActivity(PackageParser.Activity a, String type) {
2922 mActivities.put(a.component, a);
2923 if (SHOW_INFO || Config.LOGV) Log.v(
2924 TAG, " " + type + " " +
2925 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2926 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2927 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02002928 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2930 if (SHOW_INFO || Config.LOGV) {
2931 Log.v(TAG, " IntentFilter:");
2932 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2933 }
2934 if (!intent.debugCheck()) {
2935 Log.w(TAG, "==> For Activity " + a.info.name);
2936 }
2937 addFilter(intent);
2938 }
2939 }
2940
2941 public final void removeActivity(PackageParser.Activity a, String type) {
2942 mActivities.remove(a.component);
2943 if (SHOW_INFO || Config.LOGV) Log.v(
2944 TAG, " " + type + " " +
2945 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2946 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2947 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02002948 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2950 if (SHOW_INFO || Config.LOGV) {
2951 Log.v(TAG, " IntentFilter:");
2952 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2953 }
2954 removeFilter(intent);
2955 }
2956 }
2957
2958 @Override
2959 protected boolean allowFilterResult(
2960 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
2961 ActivityInfo filterAi = filter.activity.info;
2962 for (int i=dest.size()-1; i>=0; i--) {
2963 ActivityInfo destAi = dest.get(i).activityInfo;
2964 if (destAi.name == filterAi.name
2965 && destAi.packageName == filterAi.packageName) {
2966 return false;
2967 }
2968 }
2969 return true;
2970 }
2971
2972 @Override
2973 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
2974 int match) {
2975 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
2976 return null;
2977 }
2978 final PackageParser.Activity activity = info.activity;
2979 if (mSafeMode && (activity.info.applicationInfo.flags
2980 &ApplicationInfo.FLAG_SYSTEM) == 0) {
2981 return null;
2982 }
2983 final ResolveInfo res = new ResolveInfo();
2984 res.activityInfo = PackageParser.generateActivityInfo(activity,
2985 mFlags);
2986 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
2987 res.filter = info;
2988 }
2989 res.priority = info.getPriority();
2990 res.preferredOrder = activity.owner.mPreferredOrder;
2991 //System.out.println("Result: " + res.activityInfo.className +
2992 // " = " + res.priority);
2993 res.match = match;
2994 res.isDefault = info.hasDefault;
2995 res.labelRes = info.labelRes;
2996 res.nonLocalizedLabel = info.nonLocalizedLabel;
2997 res.icon = info.icon;
2998 return res;
2999 }
3000
3001 @Override
3002 protected void sortResults(List<ResolveInfo> results) {
3003 Collections.sort(results, mResolvePrioritySorter);
3004 }
3005
3006 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003007 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003009 out.print(prefix); out.print(
3010 Integer.toHexString(System.identityHashCode(filter.activity)));
3011 out.print(' ');
3012 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 }
3014
3015// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3016// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3017// final List<ResolveInfo> retList = Lists.newArrayList();
3018// while (i.hasNext()) {
3019// final ResolveInfo resolveInfo = i.next();
3020// if (isEnabledLP(resolveInfo.activityInfo)) {
3021// retList.add(resolveInfo);
3022// }
3023// }
3024// return retList;
3025// }
3026
3027 // Keys are String (activity class name), values are Activity.
3028 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3029 = new HashMap<ComponentName, PackageParser.Activity>();
3030 private int mFlags;
3031 }
3032
3033 private final class ServiceIntentResolver
3034 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003035 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003037 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 }
3039
Mihai Preda074edef2009-05-18 17:13:31 +02003040 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003042 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3044 }
3045
3046 public final void addService(PackageParser.Service s) {
3047 mServices.put(s.component, s);
3048 if (SHOW_INFO || Config.LOGV) Log.v(
3049 TAG, " " + (s.info.nonLocalizedLabel != null
3050 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3051 if (SHOW_INFO || Config.LOGV) Log.v(
3052 TAG, " Class=" + s.info.name);
3053 int NI = s.intents.size();
3054 int j;
3055 for (j=0; j<NI; j++) {
3056 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3057 if (SHOW_INFO || Config.LOGV) {
3058 Log.v(TAG, " IntentFilter:");
3059 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3060 }
3061 if (!intent.debugCheck()) {
3062 Log.w(TAG, "==> For Service " + s.info.name);
3063 }
3064 addFilter(intent);
3065 }
3066 }
3067
3068 public final void removeService(PackageParser.Service s) {
3069 mServices.remove(s.component);
3070 if (SHOW_INFO || Config.LOGV) Log.v(
3071 TAG, " " + (s.info.nonLocalizedLabel != null
3072 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3073 if (SHOW_INFO || Config.LOGV) Log.v(
3074 TAG, " Class=" + s.info.name);
3075 int NI = s.intents.size();
3076 int j;
3077 for (j=0; j<NI; j++) {
3078 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3079 if (SHOW_INFO || Config.LOGV) {
3080 Log.v(TAG, " IntentFilter:");
3081 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3082 }
3083 removeFilter(intent);
3084 }
3085 }
3086
3087 @Override
3088 protected boolean allowFilterResult(
3089 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3090 ServiceInfo filterSi = filter.service.info;
3091 for (int i=dest.size()-1; i>=0; i--) {
3092 ServiceInfo destAi = dest.get(i).serviceInfo;
3093 if (destAi.name == filterSi.name
3094 && destAi.packageName == filterSi.packageName) {
3095 return false;
3096 }
3097 }
3098 return true;
3099 }
3100
3101 @Override
3102 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3103 int match) {
3104 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3105 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3106 return null;
3107 }
3108 final PackageParser.Service service = info.service;
3109 if (mSafeMode && (service.info.applicationInfo.flags
3110 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3111 return null;
3112 }
3113 final ResolveInfo res = new ResolveInfo();
3114 res.serviceInfo = PackageParser.generateServiceInfo(service,
3115 mFlags);
3116 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3117 res.filter = filter;
3118 }
3119 res.priority = info.getPriority();
3120 res.preferredOrder = service.owner.mPreferredOrder;
3121 //System.out.println("Result: " + res.activityInfo.className +
3122 // " = " + res.priority);
3123 res.match = match;
3124 res.isDefault = info.hasDefault;
3125 res.labelRes = info.labelRes;
3126 res.nonLocalizedLabel = info.nonLocalizedLabel;
3127 res.icon = info.icon;
3128 return res;
3129 }
3130
3131 @Override
3132 protected void sortResults(List<ResolveInfo> results) {
3133 Collections.sort(results, mResolvePrioritySorter);
3134 }
3135
3136 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003137 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003139 out.print(prefix); out.print(
3140 Integer.toHexString(System.identityHashCode(filter.service)));
3141 out.print(' ');
3142 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 }
3144
3145// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3146// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3147// final List<ResolveInfo> retList = Lists.newArrayList();
3148// while (i.hasNext()) {
3149// final ResolveInfo resolveInfo = (ResolveInfo) i;
3150// if (isEnabledLP(resolveInfo.serviceInfo)) {
3151// retList.add(resolveInfo);
3152// }
3153// }
3154// return retList;
3155// }
3156
3157 // Keys are String (activity class name), values are Activity.
3158 private final HashMap<ComponentName, PackageParser.Service> mServices
3159 = new HashMap<ComponentName, PackageParser.Service>();
3160 private int mFlags;
3161 };
3162
3163 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3164 new Comparator<ResolveInfo>() {
3165 public int compare(ResolveInfo r1, ResolveInfo r2) {
3166 int v1 = r1.priority;
3167 int v2 = r2.priority;
3168 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3169 if (v1 != v2) {
3170 return (v1 > v2) ? -1 : 1;
3171 }
3172 v1 = r1.preferredOrder;
3173 v2 = r2.preferredOrder;
3174 if (v1 != v2) {
3175 return (v1 > v2) ? -1 : 1;
3176 }
3177 if (r1.isDefault != r2.isDefault) {
3178 return r1.isDefault ? -1 : 1;
3179 }
3180 v1 = r1.match;
3181 v2 = r2.match;
3182 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3183 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3184 }
3185 };
3186
3187 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3188 new Comparator<ProviderInfo>() {
3189 public int compare(ProviderInfo p1, ProviderInfo p2) {
3190 final int v1 = p1.initOrder;
3191 final int v2 = p2.initOrder;
3192 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3193 }
3194 };
3195
3196 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3197 IActivityManager am = ActivityManagerNative.getDefault();
3198 if (am != null) {
3199 try {
3200 final Intent intent = new Intent(action,
3201 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3202 if (extras != null) {
3203 intent.putExtras(extras);
3204 }
3205 am.broadcastIntent(
3206 null, intent,
3207 null, null, 0, null, null, null, false, false);
3208 } catch (RemoteException ex) {
3209 }
3210 }
3211 }
3212
3213 private final class AppDirObserver extends FileObserver {
3214 public AppDirObserver(String path, int mask, boolean isrom) {
3215 super(path, mask);
3216 mRootDir = path;
3217 mIsRom = isrom;
3218 }
3219
3220 public void onEvent(int event, String path) {
3221 String removedPackage = null;
3222 int removedUid = -1;
3223 String addedPackage = null;
3224 int addedUid = -1;
3225
3226 synchronized (mInstallLock) {
3227 String fullPathStr = null;
3228 File fullPath = null;
3229 if (path != null) {
3230 fullPath = new File(mRootDir, path);
3231 fullPathStr = fullPath.getPath();
3232 }
3233
3234 if (Config.LOGV) Log.v(
3235 TAG, "File " + fullPathStr + " changed: "
3236 + Integer.toHexString(event));
3237
3238 if (!isPackageFilename(path)) {
3239 if (Config.LOGV) Log.v(
3240 TAG, "Ignoring change of non-package file: " + fullPathStr);
3241 return;
3242 }
3243
3244 if ((event&REMOVE_EVENTS) != 0) {
3245 synchronized (mInstallLock) {
3246 PackageParser.Package p = mAppDirs.get(fullPathStr);
3247 if (p != null) {
3248 removePackageLI(p, true);
3249 removedPackage = p.applicationInfo.packageName;
3250 removedUid = p.applicationInfo.uid;
3251 }
3252 }
3253 }
3254
3255 if ((event&ADD_EVENTS) != 0) {
3256 PackageParser.Package p = mAppDirs.get(fullPathStr);
3257 if (p == null) {
3258 p = scanPackageLI(fullPath, fullPath, fullPath,
3259 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3260 PackageParser.PARSE_CHATTY |
3261 PackageParser.PARSE_MUST_BE_APK,
3262 SCAN_MONITOR);
3263 if (p != null) {
3264 synchronized (mPackages) {
3265 grantPermissionsLP(p, false);
3266 }
3267 addedPackage = p.applicationInfo.packageName;
3268 addedUid = p.applicationInfo.uid;
3269 }
3270 }
3271 }
3272
3273 synchronized (mPackages) {
3274 mSettings.writeLP();
3275 }
3276 }
3277
3278 if (removedPackage != null) {
3279 Bundle extras = new Bundle(1);
3280 extras.putInt(Intent.EXTRA_UID, removedUid);
3281 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3282 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3283 }
3284 if (addedPackage != null) {
3285 Bundle extras = new Bundle(1);
3286 extras.putInt(Intent.EXTRA_UID, addedUid);
3287 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3288 }
3289 }
3290
3291 private final String mRootDir;
3292 private final boolean mIsRom;
3293 }
Jacek Surazskic64322c2009-04-28 15:26:38 +02003294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 /* Called when a downloaded package installation has been confirmed by the user */
3296 public void installPackage(
3297 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazskic64322c2009-04-28 15:26:38 +02003298 installPackage(packageURI, observer, flags, null);
3299 }
3300
3301 /* Called when a downloaded package installation has been confirmed by the user */
3302 public void installPackage(
3303 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3304 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 mContext.enforceCallingOrSelfPermission(
3306 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazskic64322c2009-04-28 15:26:38 +02003307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 // Queue up an async operation since the package installation may take a little while.
3309 mHandler.post(new Runnable() {
3310 public void run() {
3311 mHandler.removeCallbacks(this);
3312 PackageInstalledInfo res;
3313 synchronized (mInstallLock) {
Jacek Surazskic64322c2009-04-28 15:26:38 +02003314 res = installPackageLI(packageURI, flags, true, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 }
3316 if (observer != null) {
3317 try {
3318 observer.packageInstalled(res.name, res.returnCode);
3319 } catch (RemoteException e) {
3320 Log.i(TAG, "Observer no longer exists.");
3321 }
3322 }
3323 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3324 // call appears in the synchronized block above.
3325 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3326 res.removedInfo.sendBroadcast(false, true);
3327 Bundle extras = new Bundle(1);
3328 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003329 final boolean update = res.removedInfo.removedPackage != null;
3330 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3332 }
3333 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3334 res.pkg.applicationInfo.packageName,
3335 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003336 if (update) {
3337 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3338 res.pkg.applicationInfo.packageName,
3339 extras);
3340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 }
3342 Runtime.getRuntime().gc();
3343 }
3344 });
3345 }
3346
3347 class PackageInstalledInfo {
3348 String name;
3349 int uid;
3350 PackageParser.Package pkg;
3351 int returnCode;
3352 PackageRemovedInfo removedInfo;
3353 }
3354
3355 /*
3356 * Install a non-existing package.
3357 */
3358 private void installNewPackageLI(String pkgName,
3359 File tmpPackageFile,
3360 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003361 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003362 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 // Remember this for later, in case we need to rollback this install
3364 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3365 res.name = pkgName;
3366 synchronized(mPackages) {
3367 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3368 // Don't allow installation over an existing package with the same name.
3369 Log.w(TAG, "Attempt to re-install " + pkgName
3370 + " without first uninstalling.");
3371 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3372 return;
3373 }
3374 }
3375 if (destPackageFile.exists()) {
3376 // It's safe to do this because we know (from the above check) that the file
3377 // isn't currently used for an installed package.
3378 destPackageFile.delete();
3379 }
3380 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3381 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3382 destResourceFile, pkg, 0,
3383 SCAN_MONITOR | SCAN_FORCE_DEX
3384 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003385 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3386 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 if (newPackage == null) {
3388 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3389 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3390 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3391 }
3392 } else {
3393 updateSettingsLI(pkgName, tmpPackageFile,
3394 destFilePath, destPackageFile,
3395 destResourceFile, pkg,
3396 newPackage,
3397 true,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003398 forwardLocked,
3399 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 res);
3401 // delete the partially installed application. the data directory will have to be
3402 // restored if it was already existing
3403 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3404 // remove package from internal structures. Note that we want deletePackageX to
3405 // delete the package data and cache directories that it created in
3406 // scanPackageLocked, unless those directories existed before we even tried to
3407 // install.
3408 deletePackageLI(
3409 pkgName, true,
3410 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3411 res.removedInfo);
3412 }
3413 }
3414 }
3415
3416 private void replacePackageLI(String pkgName,
3417 File tmpPackageFile,
3418 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003419 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003420 String installerPackageName, PackageInstalledInfo res) {
3421
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003422 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 // First find the old package info and check signatures
3424 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003425 oldPackage = mPackages.get(pkgName);
3426 if(checkSignaturesLP(pkg, oldPackage) != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3428 return;
3429 }
3430 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003431 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003433 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003435 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003436 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003438 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003439 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003440 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 }
3442 }
3443
3444 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3445 File tmpPackageFile,
3446 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003447 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003448 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 PackageParser.Package newPackage = null;
3450 String pkgName = deletedPackage.packageName;
3451 boolean deletedPkg = true;
3452 boolean updatedSettings = false;
Jacek Surazskic64322c2009-04-28 15:26:38 +02003453
3454 String oldInstallerPackageName = null;
3455 synchronized (mPackages) {
3456 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3457 }
3458
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003459 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 // First delete the existing package while retaining the data directory
3461 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3462 res.removedInfo)) {
3463 // If the existing package was'nt successfully deleted
3464 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3465 deletedPkg = false;
3466 } else {
3467 // Successfully deleted the old package. Now proceed with re-installation
3468 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3469 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3470 destResourceFile, pkg, parseFlags,
3471 SCAN_MONITOR | SCAN_FORCE_DEX
3472 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003473 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3474 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 if (newPackage == null) {
3476 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3477 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3478 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3479 }
3480 } else {
3481 updateSettingsLI(pkgName, tmpPackageFile,
3482 destFilePath, destPackageFile,
3483 destResourceFile, pkg,
3484 newPackage,
3485 true,
3486 forwardLocked,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003487 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 res);
3489 updatedSettings = true;
3490 }
3491 }
3492
3493 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3494 // If we deleted an exisiting package, the old source and resource files that we
3495 // were keeping around in case we needed them (see below) can now be deleted
3496 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3497 final ApplicationInfo installedPackageAppInfo =
3498 newPackage.applicationInfo;
3499 if (!deletedPackageAppInfo.sourceDir
3500 .equals(installedPackageAppInfo.sourceDir)) {
3501 new File(deletedPackageAppInfo.sourceDir).delete();
3502 }
3503 if (!deletedPackageAppInfo.publicSourceDir
3504 .equals(installedPackageAppInfo.publicSourceDir)) {
3505 new File(deletedPackageAppInfo.publicSourceDir).delete();
3506 }
3507 //update signature on the new package setting
3508 //this should always succeed, since we checked the
3509 //signature earlier.
3510 synchronized(mPackages) {
3511 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3512 parseFlags, true);
3513 }
3514 } else {
3515 // remove package from internal structures. Note that we want deletePackageX to
3516 // delete the package data and cache directories that it created in
3517 // scanPackageLocked, unless those directories existed before we even tried to
3518 // install.
3519 if(updatedSettings) {
3520 deletePackageLI(
3521 pkgName, true,
3522 PackageManager.DONT_DELETE_DATA,
3523 res.removedInfo);
3524 }
3525 // Since we failed to install the new package we need to restore the old
3526 // package that we deleted.
3527 if(deletedPkg) {
3528 installPackageLI(
3529 Uri.fromFile(new File(deletedPackage.mPath)),
3530 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003531 ? PackageManager.INSTALL_FORWARD_LOCK
Jacek Surazskic64322c2009-04-28 15:26:38 +02003532 : 0, false, oldInstallerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 }
3534 }
3535 }
3536
3537 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3538 File tmpPackageFile,
3539 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003540 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003541 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 PackageParser.Package newPackage = null;
3543 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003544 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 PackageParser.PARSE_IS_SYSTEM;
3546 String packageName = deletedPackage.packageName;
3547 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3548 if (packageName == null) {
3549 Log.w(TAG, "Attempt to delete null packageName.");
3550 return;
3551 }
3552 PackageParser.Package oldPkg;
3553 PackageSetting oldPkgSetting;
3554 synchronized (mPackages) {
3555 oldPkg = mPackages.get(packageName);
3556 oldPkgSetting = mSettings.mPackages.get(packageName);
3557 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3558 (oldPkgSetting == null)) {
3559 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3560 return;
3561 }
3562 }
3563 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3564 res.removedInfo.removedPackage = packageName;
3565 // Remove existing system package
3566 removePackageLI(oldPkg, true);
3567 synchronized (mPackages) {
3568 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3569 }
3570
3571 // Successfully disabled the old package. Now proceed with re-installation
3572 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3573 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3574 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3575 destResourceFile, pkg, parseFlags,
3576 SCAN_MONITOR | SCAN_FORCE_DEX
3577 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003578 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3579 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 if (newPackage == null) {
3581 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3582 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3583 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3584 }
3585 } else {
3586 updateSettingsLI(packageName, tmpPackageFile,
3587 destFilePath, destPackageFile,
3588 destResourceFile, pkg,
3589 newPackage,
3590 true,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003591 forwardLocked,
3592 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 res);
3594 updatedSettings = true;
3595 }
3596
3597 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3598 //update signature on the new package setting
3599 //this should always succeed, since we checked the
3600 //signature earlier.
3601 synchronized(mPackages) {
3602 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3603 parseFlags, true);
3604 }
3605 } else {
3606 // Re installation failed. Restore old information
3607 // Remove new pkg information
Dianne Hackborna96cbb42009-05-13 15:06:13 -07003608 if (newPackage != null) {
3609 removePackageLI(newPackage, true);
3610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 // Add back the old system package
3612 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3613 oldPkgSetting.resourcePath,
3614 oldPkg, parseFlags,
3615 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003616 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 // Restore the old system information in Settings
3618 synchronized(mPackages) {
3619 if(updatedSettings) {
3620 mSettings.enableSystemPackageLP(packageName);
Jacek Surazskic64322c2009-04-28 15:26:38 +02003621 mSettings.setInstallerPackageName(packageName,
3622 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 }
3624 mSettings.writeLP();
3625 }
3626 }
3627 }
3628
3629 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3630 String destFilePath, File destPackageFile,
3631 File destResourceFile,
3632 PackageParser.Package pkg,
3633 PackageParser.Package newPackage,
3634 boolean replacingExistingPackage,
3635 boolean forwardLocked,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003636 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 synchronized (mPackages) {
3638 //write settings. the installStatus will be incomplete at this stage.
3639 //note that the new package setting would have already been
3640 //added to mPackages. It hasn't been persisted yet.
3641 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3642 mSettings.writeLP();
3643 }
3644
3645 int retCode = 0;
3646 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3647 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3648 destPackageFile.toString());
3649 if (retCode != 0) {
3650 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3651 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3652 return;
3653 }
3654 }
3655 // XXX There are probably some big issues here: upon doing
3656 // the rename, we have reached the point of no return (the
3657 // original .apk is gone!), so we can't fail. Yet... we can.
3658 if (!tmpPackageFile.renameTo(destPackageFile)) {
3659 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3660 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3661 } else {
3662 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
3663 destResourceFile,
3664 forwardLocked);
3665 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3666 return;
3667 } else {
3668 Log.d(TAG, "New package installed in " + destPackageFile);
3669 }
3670 }
3671 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3672 if (mInstaller != null) {
3673 mInstaller.rmdex(tmpPackageFile.getPath());
3674 }
3675 }
3676
3677 synchronized (mPackages) {
3678 grantPermissionsLP(newPackage, true);
3679 res.name = pkgName;
3680 res.uid = newPackage.applicationInfo.uid;
3681 res.pkg = newPackage;
3682 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazskic64322c2009-04-28 15:26:38 +02003683 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3685 //to update install status
3686 mSettings.writeLP();
3687 }
3688 }
3689
The Android Open Source Project10592532009-03-18 17:39:46 -07003690 private PackageInstalledInfo installPackageLI(Uri pPackageURI,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003691 int pFlags, boolean newInstall, String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 File tmpPackageFile = null;
3693 String pkgName = null;
3694 boolean forwardLocked = false;
3695 boolean replacingExistingPackage = false;
3696 // Result object to be returned
3697 PackageInstalledInfo res = new PackageInstalledInfo();
3698 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3699 res.uid = -1;
3700 res.pkg = null;
3701 res.removedInfo = new PackageRemovedInfo();
3702
3703 main_flow: try {
3704 tmpPackageFile = createTempPackageFile();
3705 if (tmpPackageFile == null) {
3706 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3707 break main_flow;
3708 }
3709 tmpPackageFile.deleteOnExit(); // paranoia
3710 if (pPackageURI.getScheme().equals("file")) {
3711 final File srcPackageFile = new File(pPackageURI.getPath());
3712 // We copy the source package file to a temp file and then rename it to the
3713 // destination file in order to eliminate a window where the package directory
3714 // scanner notices the new package file but it's not completely copied yet.
3715 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3716 Log.e(TAG, "Couldn't copy package file to temp file.");
3717 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3718 break main_flow;
3719 }
3720 } else if (pPackageURI.getScheme().equals("content")) {
3721 ParcelFileDescriptor fd;
3722 try {
3723 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
3724 } catch (FileNotFoundException e) {
3725 Log.e(TAG, "Couldn't open file descriptor from download service.");
3726 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3727 break main_flow;
3728 }
3729 if (fd == null) {
3730 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3731 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3732 break main_flow;
3733 }
3734 if (Config.LOGV) {
3735 Log.v(TAG, "Opened file descriptor from download service.");
3736 }
3737 ParcelFileDescriptor.AutoCloseInputStream
3738 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3739 // We copy the source package file to a temp file and then rename it to the
3740 // destination file in order to eliminate a window where the package directory
3741 // scanner notices the new package file but it's not completely copied yet.
3742 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3743 Log.e(TAG, "Couldn't copy package stream to temp file.");
3744 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3745 break main_flow;
3746 }
3747 } else {
3748 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
3749 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3750 break main_flow;
3751 }
3752 pkgName = PackageParser.parsePackageName(
3753 tmpPackageFile.getAbsolutePath(), 0);
3754 if (pkgName == null) {
3755 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3756 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3757 break main_flow;
3758 }
3759 res.name = pkgName;
3760 //initialize some variables before installing pkg
3761 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003762 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 ? mDrmAppPrivateInstallDir
3764 : mAppInstallDir;
3765 final File destPackageFile = new File(destDir, pkgFileName);
3766 final String destFilePath = destPackageFile.getAbsolutePath();
3767 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003768 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 final String publicZipFileName = pkgName + ".zip";
3770 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3771 forwardLocked = true;
3772 } else {
3773 destResourceFile = destPackageFile;
3774 }
3775 // Retrieve PackageSettings and parse package
3776 int parseFlags = PackageParser.PARSE_CHATTY;
3777 parseFlags |= mDefParseFlags;
3778 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3779 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07003780 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3782 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3783 if (pkg == null) {
3784 res.returnCode = pp.getParseError();
3785 break main_flow;
3786 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003787 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
3788 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
3789 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
3790 break main_flow;
3791 }
3792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3794 res.returnCode = pp.getParseError();
3795 break main_flow;
3796 }
3797
3798 synchronized (mPackages) {
3799 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003800 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 && mPackages.containsKey(pkgName)) {
3802 replacingExistingPackage = true;
3803 }
3804 }
3805
3806 if(replacingExistingPackage) {
3807 replacePackageLI(pkgName,
3808 tmpPackageFile,
3809 destFilePath, destPackageFile, destResourceFile,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003810 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 res);
3812 } else {
3813 installNewPackageLI(pkgName,
3814 tmpPackageFile,
3815 destFilePath, destPackageFile, destResourceFile,
Jacek Surazskic64322c2009-04-28 15:26:38 +02003816 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 res);
3818 }
3819 } finally {
3820 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3821 tmpPackageFile.delete();
3822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003824 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003825 }
3826
3827 private int setPermissionsLI(String pkgName,
3828 PackageParser.Package newPackage,
3829 String destFilePath,
3830 File destResourceFile,
3831 boolean forwardLocked) {
3832 int retCode;
3833 if (forwardLocked) {
3834 try {
3835 extractPublicFiles(newPackage, destResourceFile);
3836 } catch (IOException e) {
3837 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3838 " forward-locked app.");
3839 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3840 } finally {
3841 //TODO clean up the extracted public files
3842 }
3843 if (mInstaller != null) {
3844 retCode = mInstaller.setForwardLockPerm(pkgName,
3845 newPackage.applicationInfo.uid);
3846 } else {
3847 final int filePermissions =
3848 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3849 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3850 newPackage.applicationInfo.uid);
3851 }
3852 } else {
3853 final int filePermissions =
3854 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3855 |FileUtils.S_IROTH;
3856 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3857 }
3858 if (retCode != 0) {
3859 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3860 + ". The return code was: " + retCode);
3861 }
3862 return PackageManager.INSTALL_SUCCEEDED;
3863 }
3864
3865 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3866 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3867 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3868 }
3869
3870 private void extractPublicFiles(PackageParser.Package newPackage,
3871 File publicZipFile) throws IOException {
3872 final ZipOutputStream publicZipOutStream =
3873 new ZipOutputStream(new FileOutputStream(publicZipFile));
3874 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3875
3876 // Copy manifest, resources.arsc and res directory to public zip
3877
3878 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3879 while (privateZipEntries.hasMoreElements()) {
3880 final ZipEntry zipEntry = privateZipEntries.nextElement();
3881 final String zipEntryName = zipEntry.getName();
3882 if ("AndroidManifest.xml".equals(zipEntryName)
3883 || "resources.arsc".equals(zipEntryName)
3884 || zipEntryName.startsWith("res/")) {
3885 try {
3886 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3887 } catch (IOException e) {
3888 try {
3889 publicZipOutStream.close();
3890 throw e;
3891 } finally {
3892 publicZipFile.delete();
3893 }
3894 }
3895 }
3896 }
3897
3898 publicZipOutStream.close();
3899 FileUtils.setPermissions(
3900 publicZipFile.getAbsolutePath(),
3901 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
3902 -1, -1);
3903 }
3904
3905 private static void copyZipEntry(ZipEntry zipEntry,
3906 ZipFile inZipFile,
3907 ZipOutputStream outZipStream) throws IOException {
3908 byte[] buffer = new byte[4096];
3909 int num;
3910
3911 ZipEntry newEntry;
3912 if (zipEntry.getMethod() == ZipEntry.STORED) {
3913 // Preserve the STORED method of the input entry.
3914 newEntry = new ZipEntry(zipEntry);
3915 } else {
3916 // Create a new entry so that the compressed len is recomputed.
3917 newEntry = new ZipEntry(zipEntry.getName());
3918 }
3919 outZipStream.putNextEntry(newEntry);
3920
3921 InputStream data = inZipFile.getInputStream(zipEntry);
3922 while ((num = data.read(buffer)) > 0) {
3923 outZipStream.write(buffer, 0, num);
3924 }
3925 outZipStream.flush();
3926 }
3927
3928 private void deleteTempPackageFiles() {
3929 FilenameFilter filter = new FilenameFilter() {
3930 public boolean accept(File dir, String name) {
3931 return name.startsWith("vmdl") && name.endsWith(".tmp");
3932 }
3933 };
3934 String tmpFilesList[] = mAppInstallDir.list(filter);
3935 if(tmpFilesList == null) {
3936 return;
3937 }
3938 for(int i = 0; i < tmpFilesList.length; i++) {
3939 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
3940 tmpFile.delete();
3941 }
3942 }
3943
3944 private File createTempPackageFile() {
3945 File tmpPackageFile;
3946 try {
3947 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
3948 } catch (IOException e) {
3949 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
3950 return null;
3951 }
3952 try {
3953 FileUtils.setPermissions(
3954 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
3955 -1, -1);
3956 } catch (IOException e) {
3957 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
3958 return null;
3959 }
3960 return tmpPackageFile;
3961 }
3962
3963 public void deletePackage(final String packageName,
3964 final IPackageDeleteObserver observer,
3965 final int flags) {
3966 mContext.enforceCallingOrSelfPermission(
3967 android.Manifest.permission.DELETE_PACKAGES, null);
3968 // Queue up an async operation since the package deletion may take a little while.
3969 mHandler.post(new Runnable() {
3970 public void run() {
3971 mHandler.removeCallbacks(this);
3972 final boolean succeded = deletePackageX(packageName, true, true, flags);
3973 if (observer != null) {
3974 try {
3975 observer.packageDeleted(succeded);
3976 } catch (RemoteException e) {
3977 Log.i(TAG, "Observer no longer exists.");
3978 } //end catch
3979 } //end if
3980 } //end run
3981 });
3982 }
3983
3984 /**
3985 * This method is an internal method that could be get invoked either
3986 * to delete an installed package or to clean up a failed installation.
3987 * After deleting an installed package, a broadcast is sent to notify any
3988 * listeners that the package has been installed. For cleaning up a failed
3989 * installation, the broadcast is not necessary since the package's
3990 * installation wouldn't have sent the initial broadcast either
3991 * The key steps in deleting a package are
3992 * deleting the package information in internal structures like mPackages,
3993 * deleting the packages base directories through installd
3994 * updating mSettings to reflect current status
3995 * persisting settings for later use
3996 * sending a broadcast if necessary
3997 */
3998
3999 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4000 boolean deleteCodeAndResources, int flags) {
4001 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004002 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003
4004 synchronized (mInstallLock) {
4005 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4006 }
4007
4008 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004009 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4010 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4011
4012 // If the removed package was a system update, the old system packaged
4013 // was re-enabled; we need to broadcast this information
4014 if (systemUpdate) {
4015 Bundle extras = new Bundle(1);
4016 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4017 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4018
4019 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4020 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 }
4023 return res;
4024 }
4025
4026 static class PackageRemovedInfo {
4027 String removedPackage;
4028 int uid = -1;
4029 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004030 boolean isRemovedPackageSystemUpdate = false;
4031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 void sendBroadcast(boolean fullRemove, boolean replacing) {
4033 Bundle extras = new Bundle(1);
4034 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4035 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4036 if (replacing) {
4037 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4038 }
4039 if (removedPackage != null) {
4040 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4041 }
4042 if (removedUid >= 0) {
4043 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4044 }
4045 }
4046 }
4047
4048 /*
4049 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4050 * flag is not set, the data directory is removed as well.
4051 * make sure this flag is set for partially installed apps. If not its meaningless to
4052 * delete a partially installed application.
4053 */
4054 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4055 int flags) {
4056 String packageName = p.packageName;
4057 outInfo.removedPackage = packageName;
4058 removePackageLI(p, true);
4059 // Retrieve object to delete permissions for shared user later on
4060 PackageSetting deletedPs;
4061 synchronized (mPackages) {
4062 deletedPs = mSettings.mPackages.get(packageName);
4063 }
4064 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4065 if (mInstaller != null) {
4066 int retCode = mInstaller.remove(packageName);
4067 if (retCode < 0) {
4068 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4069 + packageName + ", retcode=" + retCode);
4070 // we don't consider this to be a failure of the core package deletion
4071 }
4072 } else {
4073 //for emulator
4074 PackageParser.Package pkg = mPackages.get(packageName);
4075 File dataDir = new File(pkg.applicationInfo.dataDir);
4076 dataDir.delete();
4077 }
4078 synchronized (mPackages) {
4079 outInfo.removedUid = mSettings.removePackageLP(packageName);
4080 }
4081 }
4082 synchronized (mPackages) {
4083 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4084 // remove permissions associated with package
4085 mSettings.updateSharedUserPerms (deletedPs);
4086 }
4087 // Save settings now
4088 mSettings.writeLP ();
4089 }
4090 }
4091
4092 /*
4093 * Tries to delete system package.
4094 */
4095 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004096 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 ApplicationInfo applicationInfo = p.applicationInfo;
4098 //applicable for non-partially installed applications only
4099 if (applicationInfo == null) {
4100 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4101 return false;
4102 }
4103 PackageSetting ps = null;
4104 // Confirm if the system package has been updated
4105 // An updated system app can be deleted. This will also have to restore
4106 // the system pkg from system partition
4107 synchronized (mPackages) {
4108 ps = mSettings.getDisabledSystemPkg(p.packageName);
4109 }
4110 if (ps == null) {
4111 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4112 return false;
4113 } else {
4114 Log.i(TAG, "Deleting system pkg from data partition");
4115 }
4116 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004117 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004118 boolean deleteCodeAndResources = false;
4119 if (ps.versionCode < p.mVersionCode) {
4120 // Delete code and resources for downgrades
4121 deleteCodeAndResources = true;
4122 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4123 flags &= ~PackageManager.DONT_DELETE_DATA;
4124 }
4125 } else {
4126 // Preserve data by setting flag
4127 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4128 flags |= PackageManager.DONT_DELETE_DATA;
4129 }
4130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4132 if (!ret) {
4133 return false;
4134 }
4135 synchronized (mPackages) {
4136 // Reinstate the old system package
4137 mSettings.enableSystemPackageLP(p.packageName);
4138 }
4139 // Install the system package
4140 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4141 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4142 SCAN_MONITOR);
4143
4144 if (newPkg == null) {
4145 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4146 return false;
4147 }
4148 synchronized (mPackages) {
4149 mSettings.writeLP();
4150 }
4151 return true;
4152 }
4153
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004154 private void deletePackageResourcesLI(String packageName,
4155 String sourceDir, String publicSourceDir) {
4156 File sourceFile = new File(sourceDir);
4157 if (!sourceFile.exists()) {
4158 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4159 }
4160 // Delete application's code and resources
4161 sourceFile.delete();
4162 final File publicSourceFile = new File(publicSourceDir);
4163 if (publicSourceFile.exists()) {
4164 publicSourceFile.delete();
4165 }
4166 if (mInstaller != null) {
4167 int retCode = mInstaller.rmdex(sourceFile.toString());
4168 if (retCode < 0) {
4169 Log.w(TAG, "Couldn't remove dex file for package: "
4170 + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4171 // we don't consider this to be a failure of the core package deletion
4172 }
4173 }
4174 }
4175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4177 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4178 ApplicationInfo applicationInfo = p.applicationInfo;
4179 if (applicationInfo == null) {
4180 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4181 return false;
4182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 outInfo.uid = applicationInfo.uid;
4184
4185 // Delete package data from internal structures and also remove data if flag is set
4186 removePackageDataLI(p, outInfo, flags);
4187
4188 // Delete application code and resources
4189 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004190 deletePackageResourcesLI(applicationInfo.packageName,
4191 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 }
4193 return true;
4194 }
4195
4196 /*
4197 * This method handles package deletion in general
4198 */
4199 private boolean deletePackageLI(String packageName,
4200 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4201 if (packageName == null) {
4202 Log.w(TAG, "Attempt to delete null packageName.");
4203 return false;
4204 }
4205 PackageParser.Package p;
4206 boolean dataOnly = false;
4207 synchronized (mPackages) {
4208 p = mPackages.get(packageName);
4209 if (p == null) {
4210 //this retrieves partially installed apps
4211 dataOnly = true;
4212 PackageSetting ps = mSettings.mPackages.get(packageName);
4213 if (ps == null) {
4214 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4215 return false;
4216 }
4217 p = ps.pkg;
4218 }
4219 }
4220 if (p == null) {
4221 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4222 return false;
4223 }
4224
4225 if (dataOnly) {
4226 // Delete application data first
4227 removePackageDataLI(p, outInfo, flags);
4228 return true;
4229 }
4230 // At this point the package should have ApplicationInfo associated with it
4231 if (p.applicationInfo == null) {
4232 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4233 return false;
4234 }
4235 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4236 Log.i(TAG, "Removing system package:"+p.packageName);
4237 // When an updated system application is deleted we delete the existing resources as well and
4238 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004239 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 }
4241 Log.i(TAG, "Removing non-system package:"+p.packageName);
4242 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4243 }
4244
4245 public void clearApplicationUserData(final String packageName,
4246 final IPackageDataObserver observer) {
4247 mContext.enforceCallingOrSelfPermission(
4248 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4249 // Queue up an async operation since the package deletion may take a little while.
4250 mHandler.post(new Runnable() {
4251 public void run() {
4252 mHandler.removeCallbacks(this);
4253 final boolean succeeded;
4254 synchronized (mInstallLock) {
4255 succeeded = clearApplicationUserDataLI(packageName);
4256 }
4257 if (succeeded) {
4258 // invoke DeviceStorageMonitor's update method to clear any notifications
4259 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4260 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4261 if (dsm != null) {
4262 dsm.updateMemory();
4263 }
4264 }
4265 if(observer != null) {
4266 try {
4267 observer.onRemoveCompleted(packageName, succeeded);
4268 } catch (RemoteException e) {
4269 Log.i(TAG, "Observer no longer exists.");
4270 }
4271 } //end if observer
4272 } //end run
4273 });
4274 }
4275
4276 private boolean clearApplicationUserDataLI(String packageName) {
4277 if (packageName == null) {
4278 Log.w(TAG, "Attempt to delete null packageName.");
4279 return false;
4280 }
4281 PackageParser.Package p;
4282 boolean dataOnly = false;
4283 synchronized (mPackages) {
4284 p = mPackages.get(packageName);
4285 if(p == null) {
4286 dataOnly = true;
4287 PackageSetting ps = mSettings.mPackages.get(packageName);
4288 if((ps == null) || (ps.pkg == null)) {
4289 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4290 return false;
4291 }
4292 p = ps.pkg;
4293 }
4294 }
4295 if(!dataOnly) {
4296 //need to check this only for fully installed applications
4297 if (p == null) {
4298 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4299 return false;
4300 }
4301 final ApplicationInfo applicationInfo = p.applicationInfo;
4302 if (applicationInfo == null) {
4303 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4304 return false;
4305 }
4306 }
4307 if (mInstaller != null) {
4308 int retCode = mInstaller.clearUserData(packageName);
4309 if (retCode < 0) {
4310 Log.w(TAG, "Couldn't remove cache files for package: "
4311 + packageName);
4312 return false;
4313 }
4314 }
4315 return true;
4316 }
4317
4318 public void deleteApplicationCacheFiles(final String packageName,
4319 final IPackageDataObserver observer) {
4320 mContext.enforceCallingOrSelfPermission(
4321 android.Manifest.permission.DELETE_CACHE_FILES, null);
4322 // Queue up an async operation since the package deletion may take a little while.
4323 mHandler.post(new Runnable() {
4324 public void run() {
4325 mHandler.removeCallbacks(this);
4326 final boolean succeded;
4327 synchronized (mInstallLock) {
4328 succeded = deleteApplicationCacheFilesLI(packageName);
4329 }
4330 if(observer != null) {
4331 try {
4332 observer.onRemoveCompleted(packageName, succeded);
4333 } catch (RemoteException e) {
4334 Log.i(TAG, "Observer no longer exists.");
4335 }
4336 } //end if observer
4337 } //end run
4338 });
4339 }
4340
4341 private boolean deleteApplicationCacheFilesLI(String packageName) {
4342 if (packageName == null) {
4343 Log.w(TAG, "Attempt to delete null packageName.");
4344 return false;
4345 }
4346 PackageParser.Package p;
4347 synchronized (mPackages) {
4348 p = mPackages.get(packageName);
4349 }
4350 if (p == null) {
4351 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4352 return false;
4353 }
4354 final ApplicationInfo applicationInfo = p.applicationInfo;
4355 if (applicationInfo == null) {
4356 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4357 return false;
4358 }
4359 if (mInstaller != null) {
4360 int retCode = mInstaller.deleteCacheFiles(packageName);
4361 if (retCode < 0) {
4362 Log.w(TAG, "Couldn't remove cache files for package: "
4363 + packageName);
4364 return false;
4365 }
4366 }
4367 return true;
4368 }
4369
4370 public void getPackageSizeInfo(final String packageName,
4371 final IPackageStatsObserver observer) {
4372 mContext.enforceCallingOrSelfPermission(
4373 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4374 // Queue up an async operation since the package deletion may take a little while.
4375 mHandler.post(new Runnable() {
4376 public void run() {
4377 mHandler.removeCallbacks(this);
4378 PackageStats lStats = new PackageStats(packageName);
4379 final boolean succeded;
4380 synchronized (mInstallLock) {
4381 succeded = getPackageSizeInfoLI(packageName, lStats);
4382 }
4383 if(observer != null) {
4384 try {
4385 observer.onGetStatsCompleted(lStats, succeded);
4386 } catch (RemoteException e) {
4387 Log.i(TAG, "Observer no longer exists.");
4388 }
4389 } //end if observer
4390 } //end run
4391 });
4392 }
4393
4394 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4395 if (packageName == null) {
4396 Log.w(TAG, "Attempt to get size of null packageName.");
4397 return false;
4398 }
4399 PackageParser.Package p;
4400 boolean dataOnly = false;
4401 synchronized (mPackages) {
4402 p = mPackages.get(packageName);
4403 if(p == null) {
4404 dataOnly = true;
4405 PackageSetting ps = mSettings.mPackages.get(packageName);
4406 if((ps == null) || (ps.pkg == null)) {
4407 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4408 return false;
4409 }
4410 p = ps.pkg;
4411 }
4412 }
4413 String publicSrcDir = null;
4414 if(!dataOnly) {
4415 final ApplicationInfo applicationInfo = p.applicationInfo;
4416 if (applicationInfo == null) {
4417 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4418 return false;
4419 }
4420 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4421 }
4422 if (mInstaller != null) {
4423 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4424 publicSrcDir, pStats);
4425 if (res < 0) {
4426 return false;
4427 } else {
4428 return true;
4429 }
4430 }
4431 return true;
4432 }
4433
4434
4435 public void addPackageToPreferred(String packageName) {
4436 mContext.enforceCallingOrSelfPermission(
4437 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4438
4439 synchronized (mPackages) {
4440 PackageParser.Package p = mPackages.get(packageName);
4441 if (p == null) {
4442 return;
4443 }
4444 PackageSetting ps = (PackageSetting)p.mExtras;
4445 if (ps != null) {
4446 mSettings.mPreferredPackages.remove(ps);
4447 mSettings.mPreferredPackages.add(0, ps);
4448 updatePreferredIndicesLP();
4449 mSettings.writeLP();
4450 }
4451 }
4452 }
4453
4454 public void removePackageFromPreferred(String packageName) {
4455 mContext.enforceCallingOrSelfPermission(
4456 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4457
4458 synchronized (mPackages) {
4459 PackageParser.Package p = mPackages.get(packageName);
4460 if (p == null) {
4461 return;
4462 }
4463 if (p.mPreferredOrder > 0) {
4464 PackageSetting ps = (PackageSetting)p.mExtras;
4465 if (ps != null) {
4466 mSettings.mPreferredPackages.remove(ps);
4467 p.mPreferredOrder = 0;
4468 updatePreferredIndicesLP();
4469 mSettings.writeLP();
4470 }
4471 }
4472 }
4473 }
4474
4475 private void updatePreferredIndicesLP() {
4476 final ArrayList<PackageSetting> pkgs
4477 = mSettings.mPreferredPackages;
4478 final int N = pkgs.size();
4479 for (int i=0; i<N; i++) {
4480 pkgs.get(i).pkg.mPreferredOrder = N - i;
4481 }
4482 }
4483
4484 public List<PackageInfo> getPreferredPackages(int flags) {
4485 synchronized (mPackages) {
4486 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4487 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4488 final int N = pref.size();
4489 for (int i=0; i<N; i++) {
4490 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4491 }
4492 return res;
4493 }
4494 }
4495
4496 public void addPreferredActivity(IntentFilter filter, int match,
4497 ComponentName[] set, ComponentName activity) {
4498 mContext.enforceCallingOrSelfPermission(
4499 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4500
4501 synchronized (mPackages) {
4502 Log.i(TAG, "Adding preferred activity " + activity + ":");
4503 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4504 mSettings.mPreferredActivities.addFilter(
4505 new PreferredActivity(filter, match, set, activity));
4506 mSettings.writeLP();
4507 }
4508 }
4509
4510 public void clearPackagePreferredActivities(String packageName) {
4511 mContext.enforceCallingOrSelfPermission(
4512 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4513
4514 synchronized (mPackages) {
4515 if (clearPackagePreferredActivitiesLP(packageName)) {
4516 mSettings.writeLP();
4517 }
4518 }
4519 }
4520
4521 boolean clearPackagePreferredActivitiesLP(String packageName) {
4522 boolean changed = false;
4523 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4524 while (it.hasNext()) {
4525 PreferredActivity pa = it.next();
4526 if (pa.mActivity.getPackageName().equals(packageName)) {
4527 it.remove();
4528 changed = true;
4529 }
4530 }
4531 return changed;
4532 }
4533
4534 public int getPreferredActivities(List<IntentFilter> outFilters,
4535 List<ComponentName> outActivities, String packageName) {
4536
4537 int num = 0;
4538 synchronized (mPackages) {
4539 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4540 while (it.hasNext()) {
4541 PreferredActivity pa = it.next();
4542 if (packageName == null
4543 || pa.mActivity.getPackageName().equals(packageName)) {
4544 if (outFilters != null) {
4545 outFilters.add(new IntentFilter(pa));
4546 }
4547 if (outActivities != null) {
4548 outActivities.add(pa.mActivity);
4549 }
4550 }
4551 }
4552 }
4553
4554 return num;
4555 }
4556
4557 public void setApplicationEnabledSetting(String appPackageName,
4558 int newState, int flags) {
4559 setEnabledSetting(appPackageName, null, newState, flags);
4560 }
4561
4562 public void setComponentEnabledSetting(ComponentName componentName,
4563 int newState, int flags) {
4564 setEnabledSetting(componentName.getPackageName(),
4565 componentName.getClassName(), newState, flags);
4566 }
4567
4568 private void setEnabledSetting(
4569 final String packageNameStr, String classNameStr, int newState, final int flags) {
4570 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4571 || newState == COMPONENT_ENABLED_STATE_ENABLED
4572 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4573 throw new IllegalArgumentException("Invalid new component state: "
4574 + newState);
4575 }
4576 PackageSetting pkgSetting;
4577 final int uid = Binder.getCallingUid();
4578 final int permission = mContext.checkCallingPermission(
4579 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4580 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4581 int packageUid = -1;
4582 synchronized (mPackages) {
4583 pkgSetting = mSettings.mPackages.get(packageNameStr);
4584 if (pkgSetting == null) {
4585 if (classNameStr == null) {
4586 throw new IllegalArgumentException(
4587 "Unknown package: " + packageNameStr);
4588 }
4589 throw new IllegalArgumentException(
4590 "Unknown component: " + packageNameStr
4591 + "/" + classNameStr);
4592 }
4593 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4594 throw new SecurityException(
4595 "Permission Denial: attempt to change component state from pid="
4596 + Binder.getCallingPid()
4597 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4598 }
4599 packageUid = pkgSetting.userId;
4600 if (classNameStr == null) {
4601 // We're dealing with an application/package level state change
4602 pkgSetting.enabled = newState;
4603 } else {
4604 // We're dealing with a component level state change
4605 switch (newState) {
4606 case COMPONENT_ENABLED_STATE_ENABLED:
4607 pkgSetting.enableComponentLP(classNameStr);
4608 break;
4609 case COMPONENT_ENABLED_STATE_DISABLED:
4610 pkgSetting.disableComponentLP(classNameStr);
4611 break;
4612 case COMPONENT_ENABLED_STATE_DEFAULT:
4613 pkgSetting.restoreComponentLP(classNameStr);
4614 break;
4615 default:
4616 Log.e(TAG, "Invalid new component state: " + newState);
4617 }
4618 }
4619 mSettings.writeLP();
4620 }
4621
4622 long callingId = Binder.clearCallingIdentity();
4623 try {
4624 Bundle extras = new Bundle(2);
4625 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
4626 (flags&PackageManager.DONT_KILL_APP) != 0);
4627 extras.putInt(Intent.EXTRA_UID, packageUid);
4628 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
4629 } finally {
4630 Binder.restoreCallingIdentity(callingId);
4631 }
4632 }
4633
Jacek Surazskic64322c2009-04-28 15:26:38 +02004634 public String getInstallerPackageName(String packageName) {
4635 synchronized (mPackages) {
4636 PackageSetting pkg = mSettings.mPackages.get(packageName);
4637 if (pkg == null) {
4638 throw new IllegalArgumentException("Unknown package: " + packageName);
4639 }
4640 return pkg.installerPackageName;
4641 }
4642 }
4643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 public int getApplicationEnabledSetting(String appPackageName) {
4645 synchronized (mPackages) {
4646 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
4647 if (pkg == null) {
4648 throw new IllegalArgumentException("Unknown package: " + appPackageName);
4649 }
4650 return pkg.enabled;
4651 }
4652 }
4653
4654 public int getComponentEnabledSetting(ComponentName componentName) {
4655 synchronized (mPackages) {
4656 final String packageNameStr = componentName.getPackageName();
4657 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
4658 if (pkg == null) {
4659 throw new IllegalArgumentException("Unknown component: " + componentName);
4660 }
4661 final String classNameStr = componentName.getClassName();
4662 return pkg.currentEnabledStateLP(classNameStr);
4663 }
4664 }
4665
4666 public void enterSafeMode() {
4667 if (!mSystemReady) {
4668 mSafeMode = true;
4669 }
4670 }
4671
4672 public void systemReady() {
4673 mSystemReady = true;
4674 }
4675
4676 public boolean isSafeMode() {
4677 return mSafeMode;
4678 }
4679
4680 public boolean hasSystemUidErrors() {
4681 return mHasSystemUidErrors;
4682 }
4683
4684 static String arrayToString(int[] array) {
4685 StringBuffer buf = new StringBuffer(128);
4686 buf.append('[');
4687 if (array != null) {
4688 for (int i=0; i<array.length; i++) {
4689 if (i > 0) buf.append(", ");
4690 buf.append(array[i]);
4691 }
4692 }
4693 buf.append(']');
4694 return buf.toString();
4695 }
4696
4697 @Override
4698 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4699 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4700 != PackageManager.PERMISSION_GRANTED) {
4701 pw.println("Permission Denial: can't dump ActivityManager from from pid="
4702 + Binder.getCallingPid()
4703 + ", uid=" + Binder.getCallingUid()
4704 + " without permission "
4705 + android.Manifest.permission.DUMP);
4706 return;
4707 }
4708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 synchronized (mPackages) {
4710 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004711 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 pw.println(" ");
4713 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004714 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 pw.println(" ");
4716 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004717 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 pw.println(" ");
4719 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004720 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 pw.println(" ");
4722 pw.println("Preferred Packages:");
4723 {
4724 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004725 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 }
4727 }
4728 pw.println(" ");
4729 pw.println("Permissions:");
4730 {
4731 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004732 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
4733 pw.print(Integer.toHexString(System.identityHashCode(p)));
4734 pw.println("):");
4735 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
4736 pw.print(" uid="); pw.print(p.uid);
4737 pw.print(" gids="); pw.print(arrayToString(p.gids));
4738 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 }
4740 }
4741 pw.println(" ");
4742 pw.println("Packages:");
4743 {
4744 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004745 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
4746 pw.print(Integer.toHexString(System.identityHashCode(ps)));
4747 pw.println("):");
4748 pw.print(" userId="); pw.print(ps.userId);
4749 pw.print(" gids="); pw.println(arrayToString(ps.gids));
4750 pw.print(" sharedUser="); pw.println(ps.sharedUser);
4751 pw.print(" pkg="); pw.println(ps.pkg);
4752 pw.print(" codePath="); pw.println(ps.codePathString);
4753 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004755 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004757 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
4758 pw.print(" signatures="); pw.println(ps.signatures);
4759 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
4760 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
4761 pw.print(" installStatus="); pw.print(ps.installStatus);
4762 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 if (ps.disabledComponents.size() > 0) {
4764 pw.println(" disabledComponents:");
4765 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004766 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 }
4768 }
4769 if (ps.enabledComponents.size() > 0) {
4770 pw.println(" enabledComponents:");
4771 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004772 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 }
4774 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004775 if (ps.grantedPermissions.size() > 0) {
4776 pw.println(" grantedPermissions:");
4777 for (String s : ps.grantedPermissions) {
4778 pw.print(" "); pw.println(s);
4779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004781 if (ps.loadedPermissions.size() > 0) {
4782 pw.println(" loadedPermissions:");
4783 for (String s : ps.loadedPermissions) {
4784 pw.print(" "); pw.println(s);
4785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 }
4787 }
4788 }
4789 pw.println(" ");
4790 pw.println("Shared Users:");
4791 {
4792 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004793 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
4794 pw.print(Integer.toHexString(System.identityHashCode(su)));
4795 pw.println("):");
4796 pw.print(" userId="); pw.print(su.userId);
4797 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 pw.println(" grantedPermissions:");
4799 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004800 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004801 }
4802 pw.println(" loadedPermissions:");
4803 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004804 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004805 }
4806 }
4807 }
4808 pw.println(" ");
4809 pw.println("Settings parse messages:");
4810 pw.println(mSettings.mReadMessages.toString());
4811 }
4812 }
4813
4814 static final class BasePermission {
4815 final static int TYPE_NORMAL = 0;
4816 final static int TYPE_BUILTIN = 1;
4817 final static int TYPE_DYNAMIC = 2;
4818
4819 final String name;
4820 final String sourcePackage;
4821 final int type;
4822 PackageParser.Permission perm;
4823 PermissionInfo pendingInfo;
4824 int uid;
4825 int[] gids;
4826
4827 BasePermission(String _name, String _sourcePackage, int _type) {
4828 name = _name;
4829 sourcePackage = _sourcePackage;
4830 type = _type;
4831 }
4832 }
4833
4834 static class PackageSignatures {
4835 private Signature[] mSignatures;
4836
4837 PackageSignatures(Signature[] sigs) {
4838 assignSignatures(sigs);
4839 }
4840
4841 PackageSignatures() {
4842 }
4843
4844 void writeXml(XmlSerializer serializer, String tagName,
4845 ArrayList<Signature> pastSignatures) throws IOException {
4846 if (mSignatures == null) {
4847 return;
4848 }
4849 serializer.startTag(null, tagName);
4850 serializer.attribute(null, "count",
4851 Integer.toString(mSignatures.length));
4852 for (int i=0; i<mSignatures.length; i++) {
4853 serializer.startTag(null, "cert");
4854 final Signature sig = mSignatures[i];
4855 final int sigHash = sig.hashCode();
4856 final int numPast = pastSignatures.size();
4857 int j;
4858 for (j=0; j<numPast; j++) {
4859 Signature pastSig = pastSignatures.get(j);
4860 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
4861 serializer.attribute(null, "index", Integer.toString(j));
4862 break;
4863 }
4864 }
4865 if (j >= numPast) {
4866 pastSignatures.add(sig);
4867 serializer.attribute(null, "index", Integer.toString(numPast));
4868 serializer.attribute(null, "key", sig.toCharsString());
4869 }
4870 serializer.endTag(null, "cert");
4871 }
4872 serializer.endTag(null, tagName);
4873 }
4874
4875 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
4876 throws IOException, XmlPullParserException {
4877 String countStr = parser.getAttributeValue(null, "count");
4878 if (countStr == null) {
4879 reportSettingsProblem(Log.WARN,
4880 "Error in package manager settings: <signatures> has"
4881 + " no count at " + parser.getPositionDescription());
4882 XmlUtils.skipCurrentTag(parser);
4883 }
4884 final int count = Integer.parseInt(countStr);
4885 mSignatures = new Signature[count];
4886 int pos = 0;
4887
4888 int outerDepth = parser.getDepth();
4889 int type;
4890 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4891 && (type != XmlPullParser.END_TAG
4892 || parser.getDepth() > outerDepth)) {
4893 if (type == XmlPullParser.END_TAG
4894 || type == XmlPullParser.TEXT) {
4895 continue;
4896 }
4897
4898 String tagName = parser.getName();
4899 if (tagName.equals("cert")) {
4900 if (pos < count) {
4901 String index = parser.getAttributeValue(null, "index");
4902 if (index != null) {
4903 try {
4904 int idx = Integer.parseInt(index);
4905 String key = parser.getAttributeValue(null, "key");
4906 if (key == null) {
4907 if (idx >= 0 && idx < pastSignatures.size()) {
4908 Signature sig = pastSignatures.get(idx);
4909 if (sig != null) {
4910 mSignatures[pos] = pastSignatures.get(idx);
4911 pos++;
4912 } else {
4913 reportSettingsProblem(Log.WARN,
4914 "Error in package manager settings: <cert> "
4915 + "index " + index + " is not defined at "
4916 + parser.getPositionDescription());
4917 }
4918 } else {
4919 reportSettingsProblem(Log.WARN,
4920 "Error in package manager settings: <cert> "
4921 + "index " + index + " is out of bounds at "
4922 + parser.getPositionDescription());
4923 }
4924 } else {
4925 while (pastSignatures.size() <= idx) {
4926 pastSignatures.add(null);
4927 }
4928 Signature sig = new Signature(key);
4929 pastSignatures.set(idx, sig);
4930 mSignatures[pos] = sig;
4931 pos++;
4932 }
4933 } catch (NumberFormatException e) {
4934 reportSettingsProblem(Log.WARN,
4935 "Error in package manager settings: <cert> "
4936 + "index " + index + " is not a number at "
4937 + parser.getPositionDescription());
4938 }
4939 } else {
4940 reportSettingsProblem(Log.WARN,
4941 "Error in package manager settings: <cert> has"
4942 + " no index at " + parser.getPositionDescription());
4943 }
4944 } else {
4945 reportSettingsProblem(Log.WARN,
4946 "Error in package manager settings: too "
4947 + "many <cert> tags, expected " + count
4948 + " at " + parser.getPositionDescription());
4949 }
4950 } else {
4951 reportSettingsProblem(Log.WARN,
4952 "Unknown element under <cert>: "
4953 + parser.getName());
4954 }
4955 XmlUtils.skipCurrentTag(parser);
4956 }
4957
4958 if (pos < count) {
4959 // Should never happen -- there is an error in the written
4960 // settings -- but if it does we don't want to generate
4961 // a bad array.
4962 Signature[] newSigs = new Signature[pos];
4963 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
4964 mSignatures = newSigs;
4965 }
4966 }
4967
4968 /**
4969 * If any of the given 'sigs' is contained in the existing signatures,
4970 * then completely replace the current signatures with the ones in
4971 * 'sigs'. This is used for updating an existing package to a newly
4972 * installed version.
4973 */
4974 boolean updateSignatures(Signature[] sigs, boolean update) {
4975 if (mSignatures == null) {
4976 if (update) {
4977 assignSignatures(sigs);
4978 }
4979 return true;
4980 }
4981 if (sigs == null) {
4982 return false;
4983 }
4984
4985 for (int i=0; i<sigs.length; i++) {
4986 Signature sig = sigs[i];
4987 for (int j=0; j<mSignatures.length; j++) {
4988 if (mSignatures[j].equals(sig)) {
4989 if (update) {
4990 assignSignatures(sigs);
4991 }
4992 return true;
4993 }
4994 }
4995 }
4996 return false;
4997 }
4998
4999 /**
5000 * If any of the given 'sigs' is contained in the existing signatures,
5001 * then add in any new signatures found in 'sigs'. This is used for
5002 * including a new package into an existing shared user id.
5003 */
5004 boolean mergeSignatures(Signature[] sigs, boolean update) {
5005 if (mSignatures == null) {
5006 if (update) {
5007 assignSignatures(sigs);
5008 }
5009 return true;
5010 }
5011 if (sigs == null) {
5012 return false;
5013 }
5014
5015 Signature[] added = null;
5016 int addedCount = 0;
5017 boolean haveMatch = false;
5018 for (int i=0; i<sigs.length; i++) {
5019 Signature sig = sigs[i];
5020 boolean found = false;
5021 for (int j=0; j<mSignatures.length; j++) {
5022 if (mSignatures[j].equals(sig)) {
5023 found = true;
5024 haveMatch = true;
5025 break;
5026 }
5027 }
5028
5029 if (!found) {
5030 if (added == null) {
5031 added = new Signature[sigs.length];
5032 }
5033 added[i] = sig;
5034 addedCount++;
5035 }
5036 }
5037
5038 if (!haveMatch) {
5039 // Nothing matched -- reject the new signatures.
5040 return false;
5041 }
5042 if (added == null) {
5043 // Completely matched -- nothing else to do.
5044 return true;
5045 }
5046
5047 // Add additional signatures in.
5048 if (update) {
5049 Signature[] total = new Signature[addedCount+mSignatures.length];
5050 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5051 int j = mSignatures.length;
5052 for (int i=0; i<added.length; i++) {
5053 if (added[i] != null) {
5054 total[j] = added[i];
5055 j++;
5056 }
5057 }
5058 mSignatures = total;
5059 }
5060 return true;
5061 }
5062
5063 private void assignSignatures(Signature[] sigs) {
5064 if (sigs == null) {
5065 mSignatures = null;
5066 return;
5067 }
5068 mSignatures = new Signature[sigs.length];
5069 for (int i=0; i<sigs.length; i++) {
5070 mSignatures[i] = sigs[i];
5071 }
5072 }
5073
5074 @Override
5075 public String toString() {
5076 StringBuffer buf = new StringBuffer(128);
5077 buf.append("PackageSignatures{");
5078 buf.append(Integer.toHexString(System.identityHashCode(this)));
5079 buf.append(" [");
5080 if (mSignatures != null) {
5081 for (int i=0; i<mSignatures.length; i++) {
5082 if (i > 0) buf.append(", ");
5083 buf.append(Integer.toHexString(
5084 System.identityHashCode(mSignatures[i])));
5085 }
5086 }
5087 buf.append("]}");
5088 return buf.toString();
5089 }
5090 }
5091
5092 static class PreferredActivity extends IntentFilter {
5093 final int mMatch;
5094 final String[] mSetPackages;
5095 final String[] mSetClasses;
5096 final String[] mSetComponents;
5097 final ComponentName mActivity;
5098 final String mShortActivity;
5099 String mParseError;
5100
5101 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5102 ComponentName activity) {
5103 super(filter);
5104 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5105 mActivity = activity;
5106 mShortActivity = activity.flattenToShortString();
5107 mParseError = null;
5108 if (set != null) {
5109 final int N = set.length;
5110 String[] myPackages = new String[N];
5111 String[] myClasses = new String[N];
5112 String[] myComponents = new String[N];
5113 for (int i=0; i<N; i++) {
5114 ComponentName cn = set[i];
5115 if (cn == null) {
5116 mSetPackages = null;
5117 mSetClasses = null;
5118 mSetComponents = null;
5119 return;
5120 }
5121 myPackages[i] = cn.getPackageName().intern();
5122 myClasses[i] = cn.getClassName().intern();
5123 myComponents[i] = cn.flattenToShortString().intern();
5124 }
5125 mSetPackages = myPackages;
5126 mSetClasses = myClasses;
5127 mSetComponents = myComponents;
5128 } else {
5129 mSetPackages = null;
5130 mSetClasses = null;
5131 mSetComponents = null;
5132 }
5133 }
5134
5135 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5136 IOException {
5137 mShortActivity = parser.getAttributeValue(null, "name");
5138 mActivity = ComponentName.unflattenFromString(mShortActivity);
5139 if (mActivity == null) {
5140 mParseError = "Bad activity name " + mShortActivity;
5141 }
5142 String matchStr = parser.getAttributeValue(null, "match");
5143 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5144 String setCountStr = parser.getAttributeValue(null, "set");
5145 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5146
5147 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5148 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5149 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5150
5151 int setPos = 0;
5152
5153 int outerDepth = parser.getDepth();
5154 int type;
5155 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5156 && (type != XmlPullParser.END_TAG
5157 || parser.getDepth() > outerDepth)) {
5158 if (type == XmlPullParser.END_TAG
5159 || type == XmlPullParser.TEXT) {
5160 continue;
5161 }
5162
5163 String tagName = parser.getName();
5164 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5165 // + parser.getDepth() + " tag=" + tagName);
5166 if (tagName.equals("set")) {
5167 String name = parser.getAttributeValue(null, "name");
5168 if (name == null) {
5169 if (mParseError == null) {
5170 mParseError = "No name in set tag in preferred activity "
5171 + mShortActivity;
5172 }
5173 } else if (setPos >= setCount) {
5174 if (mParseError == null) {
5175 mParseError = "Too many set tags in preferred activity "
5176 + mShortActivity;
5177 }
5178 } else {
5179 ComponentName cn = ComponentName.unflattenFromString(name);
5180 if (cn == null) {
5181 if (mParseError == null) {
5182 mParseError = "Bad set name " + name + " in preferred activity "
5183 + mShortActivity;
5184 }
5185 } else {
5186 myPackages[setPos] = cn.getPackageName();
5187 myClasses[setPos] = cn.getClassName();
5188 myComponents[setPos] = name;
5189 setPos++;
5190 }
5191 }
5192 XmlUtils.skipCurrentTag(parser);
5193 } else if (tagName.equals("filter")) {
5194 //Log.i(TAG, "Starting to parse filter...");
5195 readFromXml(parser);
5196 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5197 // + parser.getDepth() + " tag=" + parser.getName());
5198 } else {
5199 reportSettingsProblem(Log.WARN,
5200 "Unknown element under <preferred-activities>: "
5201 + parser.getName());
5202 XmlUtils.skipCurrentTag(parser);
5203 }
5204 }
5205
5206 if (setPos != setCount) {
5207 if (mParseError == null) {
5208 mParseError = "Not enough set tags (expected " + setCount
5209 + " but found " + setPos + ") in " + mShortActivity;
5210 }
5211 }
5212
5213 mSetPackages = myPackages;
5214 mSetClasses = myClasses;
5215 mSetComponents = myComponents;
5216 }
5217
5218 public void writeToXml(XmlSerializer serializer) throws IOException {
5219 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5220 serializer.attribute(null, "name", mShortActivity);
5221 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5222 serializer.attribute(null, "set", Integer.toString(NS));
5223 for (int s=0; s<NS; s++) {
5224 serializer.startTag(null, "set");
5225 serializer.attribute(null, "name", mSetComponents[s]);
5226 serializer.endTag(null, "set");
5227 }
5228 serializer.startTag(null, "filter");
5229 super.writeToXml(serializer);
5230 serializer.endTag(null, "filter");
5231 }
5232
5233 boolean sameSet(List<ResolveInfo> query, int priority) {
5234 if (mSetPackages == null) return false;
5235 final int NQ = query.size();
5236 final int NS = mSetPackages.length;
5237 int numMatch = 0;
5238 for (int i=0; i<NQ; i++) {
5239 ResolveInfo ri = query.get(i);
5240 if (ri.priority != priority) continue;
5241 ActivityInfo ai = ri.activityInfo;
5242 boolean good = false;
5243 for (int j=0; j<NS; j++) {
5244 if (mSetPackages[j].equals(ai.packageName)
5245 && mSetClasses[j].equals(ai.name)) {
5246 numMatch++;
5247 good = true;
5248 break;
5249 }
5250 }
5251 if (!good) return false;
5252 }
5253 return numMatch == NS;
5254 }
5255 }
5256
5257 static class GrantedPermissions {
5258 final int pkgFlags;
5259
5260 HashSet<String> grantedPermissions = new HashSet<String>();
5261 int[] gids;
5262
5263 HashSet<String> loadedPermissions = new HashSet<String>();
5264
5265 GrantedPermissions(int pkgFlags) {
5266 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5267 }
5268 }
5269
5270 /**
5271 * Settings base class for pending and resolved classes.
5272 */
5273 static class PackageSettingBase extends GrantedPermissions {
5274 final String name;
5275 final File codePath;
5276 final String codePathString;
5277 final File resourcePath;
5278 final String resourcePathString;
5279 private long timeStamp;
5280 private String timeStampString = "0";
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005281 final int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282
5283 PackageSignatures signatures = new PackageSignatures();
5284
5285 boolean permissionsFixed;
5286
5287 /* Explicitly disabled components */
5288 HashSet<String> disabledComponents = new HashSet<String>(0);
5289 /* Explicitly enabled components */
5290 HashSet<String> enabledComponents = new HashSet<String>(0);
5291 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5292 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazskic64322c2009-04-28 15:26:38 +02005293
5294 /* package name of the app that installed this package */
5295 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296
5297 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005298 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 super(pkgFlags);
5300 this.name = name;
5301 this.codePath = codePath;
5302 this.codePathString = codePath.toString();
5303 this.resourcePath = resourcePath;
5304 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005305 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 }
5307
Jacek Surazskic64322c2009-04-28 15:26:38 +02005308 public void setInstallerPackageName(String packageName) {
5309 installerPackageName = packageName;
5310 }
5311
5312 String getInstallerPackageName() {
5313 return installerPackageName;
5314 }
5315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 public void setInstallStatus(int newStatus) {
5317 installStatus = newStatus;
5318 }
5319
5320 public int getInstallStatus() {
5321 return installStatus;
5322 }
5323
5324 public void setTimeStamp(long newStamp) {
5325 if (newStamp != timeStamp) {
5326 timeStamp = newStamp;
5327 timeStampString = Long.toString(newStamp);
5328 }
5329 }
5330
5331 public void setTimeStamp(long newStamp, String newStampStr) {
5332 timeStamp = newStamp;
5333 timeStampString = newStampStr;
5334 }
5335
5336 public long getTimeStamp() {
5337 return timeStamp;
5338 }
5339
5340 public String getTimeStampStr() {
5341 return timeStampString;
5342 }
5343
5344 public void copyFrom(PackageSettingBase base) {
5345 grantedPermissions = base.grantedPermissions;
5346 gids = base.gids;
5347 loadedPermissions = base.loadedPermissions;
5348
5349 timeStamp = base.timeStamp;
5350 timeStampString = base.timeStampString;
5351 signatures = base.signatures;
5352 permissionsFixed = base.permissionsFixed;
5353 disabledComponents = base.disabledComponents;
5354 enabledComponents = base.enabledComponents;
5355 enabled = base.enabled;
5356 installStatus = base.installStatus;
5357 }
5358
5359 void enableComponentLP(String componentClassName) {
5360 disabledComponents.remove(componentClassName);
5361 enabledComponents.add(componentClassName);
5362 }
5363
5364 void disableComponentLP(String componentClassName) {
5365 enabledComponents.remove(componentClassName);
5366 disabledComponents.add(componentClassName);
5367 }
5368
5369 void restoreComponentLP(String componentClassName) {
5370 enabledComponents.remove(componentClassName);
5371 disabledComponents.remove(componentClassName);
5372 }
5373
5374 int currentEnabledStateLP(String componentName) {
5375 if (enabledComponents.contains(componentName)) {
5376 return COMPONENT_ENABLED_STATE_ENABLED;
5377 } else if (disabledComponents.contains(componentName)) {
5378 return COMPONENT_ENABLED_STATE_DISABLED;
5379 } else {
5380 return COMPONENT_ENABLED_STATE_DEFAULT;
5381 }
5382 }
5383 }
5384
5385 /**
5386 * Settings data for a particular package we know about.
5387 */
5388 static final class PackageSetting extends PackageSettingBase {
5389 int userId;
5390 PackageParser.Package pkg;
5391 SharedUserSetting sharedUser;
5392
5393 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005394 int pVersionCode, int pkgFlags) {
5395 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 }
5397
5398 @Override
5399 public String toString() {
5400 return "PackageSetting{"
5401 + Integer.toHexString(System.identityHashCode(this))
5402 + " " + name + "/" + userId + "}";
5403 }
5404 }
5405
5406 /**
5407 * Settings data for a particular shared user ID we know about.
5408 */
5409 static final class SharedUserSetting extends GrantedPermissions {
5410 final String name;
5411 int userId;
5412 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5413 final PackageSignatures signatures = new PackageSignatures();
5414
5415 SharedUserSetting(String _name, int _pkgFlags) {
5416 super(_pkgFlags);
5417 name = _name;
5418 }
5419
5420 @Override
5421 public String toString() {
5422 return "SharedUserSetting{"
5423 + Integer.toHexString(System.identityHashCode(this))
5424 + " " + name + "/" + userId + "}";
5425 }
5426 }
5427
5428 /**
5429 * Holds information about dynamic settings.
5430 */
5431 private static final class Settings {
5432 private final File mSettingsFilename;
5433 private final File mBackupSettingsFilename;
5434 private final HashMap<String, PackageSetting> mPackages =
5435 new HashMap<String, PackageSetting>();
5436 // The user's preferred packages/applications, in order of preference.
5437 // First is the most preferred.
5438 private final ArrayList<PackageSetting> mPreferredPackages =
5439 new ArrayList<PackageSetting>();
5440 // List of replaced system applications
5441 final HashMap<String, PackageSetting> mDisabledSysPackages =
5442 new HashMap<String, PackageSetting>();
5443
5444 // The user's preferred activities associated with particular intent
5445 // filters.
5446 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5447 new IntentResolver<PreferredActivity, PreferredActivity>() {
5448 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005449 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005450 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005451 out.print(prefix); out.print(
5452 Integer.toHexString(System.identityHashCode(filter)));
5453 out.print(' ');
5454 out.print(filter.mActivity.flattenToShortString());
5455 out.print(" match=0x");
5456 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005458 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005460 out.print(prefix); out.print(" ");
5461 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 }
5463 }
5464 }
5465 };
5466 private final HashMap<String, SharedUserSetting> mSharedUsers =
5467 new HashMap<String, SharedUserSetting>();
5468 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5469 private final SparseArray<Object> mOtherUserIds =
5470 new SparseArray<Object>();
5471
5472 // For reading/writing settings file.
5473 private final ArrayList<Signature> mPastSignatures =
5474 new ArrayList<Signature>();
5475
5476 // Mapping from permission names to info about them.
5477 final HashMap<String, BasePermission> mPermissions =
5478 new HashMap<String, BasePermission>();
5479
5480 // Mapping from permission tree names to info about them.
5481 final HashMap<String, BasePermission> mPermissionTrees =
5482 new HashMap<String, BasePermission>();
5483
5484 private final ArrayList<String> mPendingPreferredPackages
5485 = new ArrayList<String>();
5486
5487 private final StringBuilder mReadMessages = new StringBuilder();
5488
5489 private static final class PendingPackage extends PackageSettingBase {
5490 final int sharedId;
5491
5492 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005493 int sharedId, int pVersionCode, int pkgFlags) {
5494 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 this.sharedId = sharedId;
5496 }
5497 }
5498 private final ArrayList<PendingPackage> mPendingPackages
5499 = new ArrayList<PendingPackage>();
5500
5501 Settings() {
5502 File dataDir = Environment.getDataDirectory();
5503 File systemDir = new File(dataDir, "system");
5504 systemDir.mkdirs();
5505 FileUtils.setPermissions(systemDir.toString(),
5506 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5507 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5508 -1, -1);
5509 mSettingsFilename = new File(systemDir, "packages.xml");
5510 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5511 }
5512
5513 PackageSetting getPackageLP(PackageParser.Package pkg,
5514 SharedUserSetting sharedUser, File codePath, File resourcePath,
5515 int pkgFlags, boolean create, boolean add) {
5516 final String name = pkg.packageName;
5517 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005518 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519
5520 if (p != null) {
5521 p.pkg = pkg;
5522 }
5523 return p;
5524 }
5525
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005526 PackageSetting peekPackageLP(String name) {
5527 return mPackages.get(name);
5528 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 PackageSetting p = mPackages.get(name);
5530 if (p != null && p.codePath.getPath().equals(codePath)) {
5531 return p;
5532 }
5533 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005534 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 }
5536
5537 void setInstallStatus(String pkgName, int status) {
5538 PackageSetting p = mPackages.get(pkgName);
5539 if(p != null) {
5540 if(p.getInstallStatus() != status) {
5541 p.setInstallStatus(status);
5542 }
5543 }
5544 }
5545
Jacek Surazskic64322c2009-04-28 15:26:38 +02005546 void setInstallerPackageName(String pkgName,
5547 String installerPkgName) {
5548 PackageSetting p = mPackages.get(pkgName);
5549 if(p != null) {
5550 p.setInstallerPackageName(installerPkgName);
5551 }
5552 }
5553
5554 String getInstallerPackageName(String pkgName) {
5555 PackageSetting p = mPackages.get(pkgName);
5556 return (p == null) ? null : p.getInstallerPackageName();
5557 }
5558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 int getInstallStatus(String pkgName) {
5560 PackageSetting p = mPackages.get(pkgName);
5561 if(p != null) {
5562 return p.getInstallStatus();
5563 }
5564 return -1;
5565 }
5566
5567 SharedUserSetting getSharedUserLP(String name,
5568 int pkgFlags, boolean create) {
5569 SharedUserSetting s = mSharedUsers.get(name);
5570 if (s == null) {
5571 if (!create) {
5572 return null;
5573 }
5574 s = new SharedUserSetting(name, pkgFlags);
5575 if (MULTIPLE_APPLICATION_UIDS) {
5576 s.userId = newUserIdLP(s);
5577 } else {
5578 s.userId = FIRST_APPLICATION_UID;
5579 }
5580 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
5581 // < 0 means we couldn't assign a userid; fall out and return
5582 // s, which is currently null
5583 if (s.userId >= 0) {
5584 mSharedUsers.put(name, s);
5585 }
5586 }
5587
5588 return s;
5589 }
5590
5591 int disableSystemPackageLP(String name) {
5592 PackageSetting p = mPackages.get(name);
5593 if(p == null) {
5594 Log.w(TAG, "Package:"+name+" is not an installed package");
5595 return -1;
5596 }
5597 PackageSetting dp = mDisabledSysPackages.get(name);
5598 // always make sure the system package code and resource paths dont change
5599 if(dp == null) {
5600 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5601 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5602 }
5603 mDisabledSysPackages.put(name, p);
5604 }
5605 return removePackageLP(name);
5606 }
5607
5608 PackageSetting enableSystemPackageLP(String name) {
5609 PackageSetting p = mDisabledSysPackages.get(name);
5610 if(p == null) {
5611 Log.w(TAG, "Package:"+name+" is not disabled");
5612 return null;
5613 }
5614 // Reset flag in ApplicationInfo object
5615 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5616 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5617 }
5618 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005619 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 mDisabledSysPackages.remove(name);
5621 return ret;
5622 }
5623
5624 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005625 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 PackageSetting p = mPackages.get(name);
5627 if (p != null) {
5628 if (p.userId == uid) {
5629 return p;
5630 }
5631 reportSettingsProblem(Log.ERROR,
5632 "Adding duplicate package, keeping first: " + name);
5633 return null;
5634 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005635 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 p.userId = uid;
5637 if (addUserIdLP(uid, p, name)) {
5638 mPackages.put(name, p);
5639 return p;
5640 }
5641 return null;
5642 }
5643
5644 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
5645 SharedUserSetting s = mSharedUsers.get(name);
5646 if (s != null) {
5647 if (s.userId == uid) {
5648 return s;
5649 }
5650 reportSettingsProblem(Log.ERROR,
5651 "Adding duplicate shared user, keeping first: " + name);
5652 return null;
5653 }
5654 s = new SharedUserSetting(name, pkgFlags);
5655 s.userId = uid;
5656 if (addUserIdLP(uid, s, name)) {
5657 mSharedUsers.put(name, s);
5658 return s;
5659 }
5660 return null;
5661 }
5662
5663 private PackageSetting getPackageLP(String name,
5664 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005665 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 PackageSetting p = mPackages.get(name);
5667 if (p != null) {
5668 if (!p.codePath.equals(codePath)) {
5669 // Check to see if its a disabled system app
5670 PackageSetting ps = mDisabledSysPackages.get(name);
5671 if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
5672 // Could be a replaced system package
5673 // Note that if the user replaced a system app, the user has to physically
5674 // delete the new one in order to revert to the system app. So even
5675 // if the user updated the system app via an update, the user still
5676 // has to delete the one installed in the data partition in order to pick up the
5677 // new system package.
5678 return p;
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07005679 } else if ((p.pkg != null) && (p.pkg.applicationInfo != null) &&
5680 ((p.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
5681 // Check for non-system apps
5682 reportSettingsProblem(Log.WARN,
5683 "Package " + name + " codePath changed from " + p.codePath
5684 + " to " + codePath + "; Retaining data and using new code");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 } else {
5686 reportSettingsProblem(Log.WARN,
5687 "Package " + name + " codePath changed from " + p.codePath
5688 + " to " + codePath + "; replacing with new");
5689 p = null;
5690 }
5691 } else if (p.sharedUser != sharedUser) {
5692 reportSettingsProblem(Log.WARN,
5693 "Package " + name + " shared user changed from "
5694 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
5695 + " to "
5696 + (sharedUser != null ? sharedUser.name : "<nothing>")
5697 + "; replacing with new");
5698 p = null;
5699 }
5700 }
5701 if (p == null) {
5702 // Create a new PackageSettings entry. this can end up here because
5703 // of code path mismatch or user id mismatch of an updated system partition
5704 if (!create) {
5705 return null;
5706 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005707 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005708 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07005709 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 if (sharedUser != null) {
5711 p.userId = sharedUser.userId;
5712 } else if (MULTIPLE_APPLICATION_UIDS) {
5713 p.userId = newUserIdLP(p);
5714 } else {
5715 p.userId = FIRST_APPLICATION_UID;
5716 }
5717 if (p.userId < 0) {
5718 reportSettingsProblem(Log.WARN,
5719 "Package " + name + " could not be assigned a valid uid");
5720 return null;
5721 }
5722 if (add) {
5723 // Finish adding new package by adding it and updating shared
5724 // user preferences
5725 insertPackageSettingLP(p, name, sharedUser);
5726 }
5727 }
5728 return p;
5729 }
5730
5731 // Utility method that adds a PackageSetting to mPackages and
5732 // completes updating the shared user attributes
5733 private void insertPackageSettingLP(PackageSetting p, String name,
5734 SharedUserSetting sharedUser) {
5735 mPackages.put(name, p);
5736 if (sharedUser != null) {
5737 if (p.sharedUser != null && p.sharedUser != sharedUser) {
5738 reportSettingsProblem(Log.ERROR,
5739 "Package " + p.name + " was user "
5740 + p.sharedUser + " but is now " + sharedUser
5741 + "; I am not changing its files so it will probably fail!");
5742 p.sharedUser.packages.remove(p);
5743 } else if (p.userId != sharedUser.userId) {
5744 reportSettingsProblem(Log.ERROR,
5745 "Package " + p.name + " was user id " + p.userId
5746 + " but is now user " + sharedUser
5747 + " with id " + sharedUser.userId
5748 + "; I am not changing its files so it will probably fail!");
5749 }
5750
5751 sharedUser.packages.add(p);
5752 p.sharedUser = sharedUser;
5753 p.userId = sharedUser.userId;
5754 }
5755 }
5756
5757 private void updateSharedUserPerms (PackageSetting deletedPs) {
5758 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
5759 Log.i(TAG, "Trying to update info for null package. Just ignoring");
5760 return;
5761 }
5762 // No sharedUserId
5763 if (deletedPs.sharedUser == null) {
5764 return;
5765 }
5766 SharedUserSetting sus = deletedPs.sharedUser;
5767 // Update permissions
5768 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
5769 boolean used = false;
5770 if (!sus.grantedPermissions.contains (eachPerm)) {
5771 continue;
5772 }
5773 for (PackageSetting pkg:sus.packages) {
5774 if (pkg.grantedPermissions.contains (eachPerm)) {
5775 used = true;
5776 break;
5777 }
5778 }
5779 if (!used) {
5780 // can safely delete this permission from list
5781 sus.grantedPermissions.remove(eachPerm);
5782 sus.loadedPermissions.remove(eachPerm);
5783 }
5784 }
5785 // Update gids
5786 int newGids[] = null;
5787 for (PackageSetting pkg:sus.packages) {
5788 newGids = appendInts(newGids, pkg.gids);
5789 }
5790 sus.gids = newGids;
5791 }
5792
5793 private int removePackageLP(String name) {
5794 PackageSetting p = mPackages.get(name);
5795 if (p != null) {
5796 mPackages.remove(name);
5797 if (p.sharedUser != null) {
5798 p.sharedUser.packages.remove(p);
5799 if (p.sharedUser.packages.size() == 0) {
5800 mSharedUsers.remove(p.sharedUser.name);
5801 removeUserIdLP(p.sharedUser.userId);
5802 return p.sharedUser.userId;
5803 }
5804 } else {
5805 removeUserIdLP(p.userId);
5806 return p.userId;
5807 }
5808 }
5809 return -1;
5810 }
5811
5812 private boolean addUserIdLP(int uid, Object obj, Object name) {
5813 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
5814 return false;
5815 }
5816
5817 if (uid >= FIRST_APPLICATION_UID) {
5818 int N = mUserIds.size();
5819 final int index = uid - FIRST_APPLICATION_UID;
5820 while (index >= N) {
5821 mUserIds.add(null);
5822 N++;
5823 }
5824 if (mUserIds.get(index) != null) {
5825 reportSettingsProblem(Log.ERROR,
5826 "Adding duplicate shared id: " + uid
5827 + " name=" + name);
5828 return false;
5829 }
5830 mUserIds.set(index, obj);
5831 } else {
5832 if (mOtherUserIds.get(uid) != null) {
5833 reportSettingsProblem(Log.ERROR,
5834 "Adding duplicate shared id: " + uid
5835 + " name=" + name);
5836 return false;
5837 }
5838 mOtherUserIds.put(uid, obj);
5839 }
5840 return true;
5841 }
5842
5843 public Object getUserIdLP(int uid) {
5844 if (uid >= FIRST_APPLICATION_UID) {
5845 int N = mUserIds.size();
5846 final int index = uid - FIRST_APPLICATION_UID;
5847 return index < N ? mUserIds.get(index) : null;
5848 } else {
5849 return mOtherUserIds.get(uid);
5850 }
5851 }
5852
5853 private void removeUserIdLP(int uid) {
5854 if (uid >= FIRST_APPLICATION_UID) {
5855 int N = mUserIds.size();
5856 final int index = uid - FIRST_APPLICATION_UID;
5857 if (index < N) mUserIds.set(index, null);
5858 } else {
5859 mOtherUserIds.remove(uid);
5860 }
5861 }
5862
5863 void writeLP() {
5864 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
5865
5866 // Keep the old settings around until we know the new ones have
5867 // been successfully written.
5868 if (mSettingsFilename.exists()) {
5869 if (mBackupSettingsFilename.exists()) {
5870 mBackupSettingsFilename.delete();
5871 }
5872 mSettingsFilename.renameTo(mBackupSettingsFilename);
5873 }
5874
5875 mPastSignatures.clear();
5876
5877 try {
5878 FileOutputStream str = new FileOutputStream(mSettingsFilename);
5879
5880 //XmlSerializer serializer = XmlUtils.serializerInstance();
5881 XmlSerializer serializer = new FastXmlSerializer();
5882 serializer.setOutput(str, "utf-8");
5883 serializer.startDocument(null, true);
5884 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
5885
5886 serializer.startTag(null, "packages");
5887
5888 serializer.startTag(null, "permission-trees");
5889 for (BasePermission bp : mPermissionTrees.values()) {
5890 writePermission(serializer, bp);
5891 }
5892 serializer.endTag(null, "permission-trees");
5893
5894 serializer.startTag(null, "permissions");
5895 for (BasePermission bp : mPermissions.values()) {
5896 writePermission(serializer, bp);
5897 }
5898 serializer.endTag(null, "permissions");
5899
5900 for (PackageSetting pkg : mPackages.values()) {
5901 writePackage(serializer, pkg);
5902 }
5903
5904 for (PackageSetting pkg : mDisabledSysPackages.values()) {
5905 writeDisabledSysPackage(serializer, pkg);
5906 }
5907
5908 serializer.startTag(null, "preferred-packages");
5909 int N = mPreferredPackages.size();
5910 for (int i=0; i<N; i++) {
5911 PackageSetting pkg = mPreferredPackages.get(i);
5912 serializer.startTag(null, "item");
5913 serializer.attribute(null, "name", pkg.name);
5914 serializer.endTag(null, "item");
5915 }
5916 serializer.endTag(null, "preferred-packages");
5917
5918 serializer.startTag(null, "preferred-activities");
5919 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
5920 serializer.startTag(null, "item");
5921 pa.writeToXml(serializer);
5922 serializer.endTag(null, "item");
5923 }
5924 serializer.endTag(null, "preferred-activities");
5925
5926 for (SharedUserSetting usr : mSharedUsers.values()) {
5927 serializer.startTag(null, "shared-user");
5928 serializer.attribute(null, "name", usr.name);
5929 serializer.attribute(null, "userId",
5930 Integer.toString(usr.userId));
5931 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
5932 serializer.startTag(null, "perms");
5933 for (String name : usr.grantedPermissions) {
5934 serializer.startTag(null, "item");
5935 serializer.attribute(null, "name", name);
5936 serializer.endTag(null, "item");
5937 }
5938 serializer.endTag(null, "perms");
5939 serializer.endTag(null, "shared-user");
5940 }
5941
5942 serializer.endTag(null, "packages");
5943
5944 serializer.endDocument();
5945
5946 str.flush();
5947 str.close();
5948
5949 // New settings successfully written, old ones are no longer
5950 // needed.
5951 mBackupSettingsFilename.delete();
5952 FileUtils.setPermissions(mSettingsFilename.toString(),
5953 FileUtils.S_IRUSR|FileUtils.S_IWUSR
5954 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
5955 |FileUtils.S_IROTH,
5956 -1, -1);
5957
5958 } catch(XmlPullParserException e) {
5959 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5960
5961 } catch(java.io.IOException e) {
5962 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5963
5964 }
5965
5966 //Debug.stopMethodTracing();
5967 }
5968
5969 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
5970 throws java.io.IOException {
5971 serializer.startTag(null, "updated-package");
5972 serializer.attribute(null, "name", pkg.name);
5973 serializer.attribute(null, "codePath", pkg.codePathString);
5974 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005975 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5977 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5978 }
5979 if (pkg.sharedUser == null) {
5980 serializer.attribute(null, "userId",
5981 Integer.toString(pkg.userId));
5982 } else {
5983 serializer.attribute(null, "sharedUserId",
5984 Integer.toString(pkg.userId));
5985 }
5986 serializer.startTag(null, "perms");
5987 if (pkg.sharedUser == null) {
5988 // If this is a shared user, the permissions will
5989 // be written there. We still need to write an
5990 // empty permissions list so permissionsFixed will
5991 // be set.
5992 for (final String name : pkg.grantedPermissions) {
5993 BasePermission bp = mPermissions.get(name);
5994 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
5995 // We only need to write signature or system permissions but this wont
5996 // match the semantics of grantedPermissions. So write all permissions.
5997 serializer.startTag(null, "item");
5998 serializer.attribute(null, "name", name);
5999 serializer.endTag(null, "item");
6000 }
6001 }
6002 }
6003 serializer.endTag(null, "perms");
6004 serializer.endTag(null, "updated-package");
6005 }
6006
6007 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6008 throws java.io.IOException {
6009 serializer.startTag(null, "package");
6010 serializer.attribute(null, "name", pkg.name);
6011 serializer.attribute(null, "codePath", pkg.codePathString);
6012 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6013 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6014 }
6015 serializer.attribute(null, "system",
6016 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6017 ? "true" : "false");
6018 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006019 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 if (pkg.sharedUser == null) {
6021 serializer.attribute(null, "userId",
6022 Integer.toString(pkg.userId));
6023 } else {
6024 serializer.attribute(null, "sharedUserId",
6025 Integer.toString(pkg.userId));
6026 }
6027 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6028 serializer.attribute(null, "enabled",
6029 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6030 ? "true" : "false");
6031 }
6032 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6033 serializer.attribute(null, "installStatus", "false");
6034 }
Jacek Surazskic64322c2009-04-28 15:26:38 +02006035 if (pkg.installerPackageName != null) {
6036 serializer.attribute(null, "installer", pkg.installerPackageName);
6037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6039 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6040 serializer.startTag(null, "perms");
6041 if (pkg.sharedUser == null) {
6042 // If this is a shared user, the permissions will
6043 // be written there. We still need to write an
6044 // empty permissions list so permissionsFixed will
6045 // be set.
6046 for (final String name : pkg.grantedPermissions) {
6047 serializer.startTag(null, "item");
6048 serializer.attribute(null, "name", name);
6049 serializer.endTag(null, "item");
6050 }
6051 }
6052 serializer.endTag(null, "perms");
6053 }
6054 if (pkg.disabledComponents.size() > 0) {
6055 serializer.startTag(null, "disabled-components");
6056 for (final String name : pkg.disabledComponents) {
6057 serializer.startTag(null, "item");
6058 serializer.attribute(null, "name", name);
6059 serializer.endTag(null, "item");
6060 }
6061 serializer.endTag(null, "disabled-components");
6062 }
6063 if (pkg.enabledComponents.size() > 0) {
6064 serializer.startTag(null, "enabled-components");
6065 for (final String name : pkg.enabledComponents) {
6066 serializer.startTag(null, "item");
6067 serializer.attribute(null, "name", name);
6068 serializer.endTag(null, "item");
6069 }
6070 serializer.endTag(null, "enabled-components");
6071 }
Jacek Surazskic64322c2009-04-28 15:26:38 +02006072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006073 serializer.endTag(null, "package");
6074 }
6075
6076 void writePermission(XmlSerializer serializer, BasePermission bp)
6077 throws XmlPullParserException, java.io.IOException {
6078 if (bp.type != BasePermission.TYPE_BUILTIN
6079 && bp.sourcePackage != null) {
6080 serializer.startTag(null, "item");
6081 serializer.attribute(null, "name", bp.name);
6082 serializer.attribute(null, "package", bp.sourcePackage);
6083 if (DEBUG_SETTINGS) Log.v(TAG,
6084 "Writing perm: name=" + bp.name + " type=" + bp.type);
6085 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6086 PermissionInfo pi = bp.perm != null ? bp.perm.info
6087 : bp.pendingInfo;
6088 if (pi != null) {
6089 serializer.attribute(null, "type", "dynamic");
6090 if (pi.icon != 0) {
6091 serializer.attribute(null, "icon",
6092 Integer.toString(pi.icon));
6093 }
6094 if (pi.nonLocalizedLabel != null) {
6095 serializer.attribute(null, "label",
6096 pi.nonLocalizedLabel.toString());
6097 }
6098 if (pi.protectionLevel !=
6099 PermissionInfo.PROTECTION_NORMAL) {
6100 serializer.attribute(null, "protection",
6101 Integer.toString(pi.protectionLevel));
6102 }
6103 }
6104 }
6105 serializer.endTag(null, "item");
6106 }
6107 }
6108
6109 String getReadMessagesLP() {
6110 return mReadMessages.toString();
6111 }
6112
6113 ArrayList<String> getListOfIncompleteInstallPackages() {
6114 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6115 Iterator<String> its = kList.iterator();
6116 ArrayList<String> ret = new ArrayList<String>();
6117 while(its.hasNext()) {
6118 String key = its.next();
6119 PackageSetting ps = mPackages.get(key);
6120 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6121 ret.add(key);
6122 }
6123 }
6124 return ret;
6125 }
6126
6127 boolean readLP() {
6128 FileInputStream str = null;
6129 if (mBackupSettingsFilename.exists()) {
6130 try {
6131 str = new FileInputStream(mBackupSettingsFilename);
6132 mReadMessages.append("Reading from backup settings file\n");
6133 Log.i(TAG, "Reading from backup settings file!");
6134 } catch (java.io.IOException e) {
6135 // We'll try for the normal settings file.
6136 }
6137 }
6138
6139 mPastSignatures.clear();
6140
6141 try {
6142 if (str == null) {
6143 if (!mSettingsFilename.exists()) {
6144 mReadMessages.append("No settings file found\n");
6145 Log.i(TAG, "No current settings file!");
6146 return false;
6147 }
6148 str = new FileInputStream(mSettingsFilename);
6149 }
6150 XmlPullParser parser = Xml.newPullParser();
6151 parser.setInput(str, null);
6152
6153 int type;
6154 while ((type=parser.next()) != XmlPullParser.START_TAG
6155 && type != XmlPullParser.END_DOCUMENT) {
6156 ;
6157 }
6158
6159 if (type != XmlPullParser.START_TAG) {
6160 mReadMessages.append("No start tag found in settings file\n");
6161 Log.e(TAG, "No start tag found in package manager settings");
6162 return false;
6163 }
6164
6165 int outerDepth = parser.getDepth();
6166 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6167 && (type != XmlPullParser.END_TAG
6168 || parser.getDepth() > outerDepth)) {
6169 if (type == XmlPullParser.END_TAG
6170 || type == XmlPullParser.TEXT) {
6171 continue;
6172 }
6173
6174 String tagName = parser.getName();
6175 if (tagName.equals("package")) {
6176 readPackageLP(parser);
6177 } else if (tagName.equals("permissions")) {
6178 readPermissionsLP(mPermissions, parser);
6179 } else if (tagName.equals("permission-trees")) {
6180 readPermissionsLP(mPermissionTrees, parser);
6181 } else if (tagName.equals("shared-user")) {
6182 readSharedUserLP(parser);
6183 } else if (tagName.equals("preferred-packages")) {
6184 readPreferredPackagesLP(parser);
6185 } else if (tagName.equals("preferred-activities")) {
6186 readPreferredActivitiesLP(parser);
6187 } else if(tagName.equals("updated-package")) {
6188 readDisabledSysPackageLP(parser);
6189 } else {
6190 Log.w(TAG, "Unknown element under <packages>: "
6191 + parser.getName());
6192 XmlUtils.skipCurrentTag(parser);
6193 }
6194 }
6195
6196 str.close();
6197
6198 } catch(XmlPullParserException e) {
6199 mReadMessages.append("Error reading: " + e.toString());
6200 Log.e(TAG, "Error reading package manager settings", e);
6201
6202 } catch(java.io.IOException e) {
6203 mReadMessages.append("Error reading: " + e.toString());
6204 Log.e(TAG, "Error reading package manager settings", e);
6205
6206 }
6207
6208 int N = mPendingPackages.size();
6209 for (int i=0; i<N; i++) {
6210 final PendingPackage pp = mPendingPackages.get(i);
6211 Object idObj = getUserIdLP(pp.sharedId);
6212 if (idObj != null && idObj instanceof SharedUserSetting) {
6213 PackageSetting p = getPackageLP(pp.name,
6214 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006215 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006216 if (p == null) {
6217 Log.w(TAG, "Unable to create application package for "
6218 + pp.name);
6219 continue;
6220 }
6221 p.copyFrom(pp);
6222 } else if (idObj != null) {
6223 String msg = "Bad package setting: package " + pp.name
6224 + " has shared uid " + pp.sharedId
6225 + " that is not a shared uid\n";
6226 mReadMessages.append(msg);
6227 Log.e(TAG, msg);
6228 } else {
6229 String msg = "Bad package setting: package " + pp.name
6230 + " has shared uid " + pp.sharedId
6231 + " that is not defined\n";
6232 mReadMessages.append(msg);
6233 Log.e(TAG, msg);
6234 }
6235 }
6236 mPendingPackages.clear();
6237
6238 N = mPendingPreferredPackages.size();
6239 mPreferredPackages.clear();
6240 for (int i=0; i<N; i++) {
6241 final String name = mPendingPreferredPackages.get(i);
6242 final PackageSetting p = mPackages.get(name);
6243 if (p != null) {
6244 mPreferredPackages.add(p);
6245 } else {
6246 Log.w(TAG, "Unknown preferred package: " + name);
6247 }
6248 }
6249 mPendingPreferredPackages.clear();
6250
6251 mReadMessages.append("Read completed successfully: "
6252 + mPackages.size() + " packages, "
6253 + mSharedUsers.size() + " shared uids\n");
6254
6255 return true;
6256 }
6257
6258 private int readInt(XmlPullParser parser, String ns, String name,
6259 int defValue) {
6260 String v = parser.getAttributeValue(ns, name);
6261 try {
6262 if (v == null) {
6263 return defValue;
6264 }
6265 return Integer.parseInt(v);
6266 } catch (NumberFormatException e) {
6267 reportSettingsProblem(Log.WARN,
6268 "Error in package manager settings: attribute " +
6269 name + " has bad integer value " + v + " at "
6270 + parser.getPositionDescription());
6271 }
6272 return defValue;
6273 }
6274
6275 private void readPermissionsLP(HashMap<String, BasePermission> out,
6276 XmlPullParser parser)
6277 throws IOException, XmlPullParserException {
6278 int outerDepth = parser.getDepth();
6279 int type;
6280 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6281 && (type != XmlPullParser.END_TAG
6282 || parser.getDepth() > outerDepth)) {
6283 if (type == XmlPullParser.END_TAG
6284 || type == XmlPullParser.TEXT) {
6285 continue;
6286 }
6287
6288 String tagName = parser.getName();
6289 if (tagName.equals("item")) {
6290 String name = parser.getAttributeValue(null, "name");
6291 String sourcePackage = parser.getAttributeValue(null, "package");
6292 String ptype = parser.getAttributeValue(null, "type");
6293 if (name != null && sourcePackage != null) {
6294 boolean dynamic = "dynamic".equals(ptype);
6295 BasePermission bp = new BasePermission(name, sourcePackage,
6296 dynamic
6297 ? BasePermission.TYPE_DYNAMIC
6298 : BasePermission.TYPE_NORMAL);
6299 if (dynamic) {
6300 PermissionInfo pi = new PermissionInfo();
6301 pi.packageName = sourcePackage.intern();
6302 pi.name = name.intern();
6303 pi.icon = readInt(parser, null, "icon", 0);
6304 pi.nonLocalizedLabel = parser.getAttributeValue(
6305 null, "label");
6306 pi.protectionLevel = readInt(parser, null, "protection",
6307 PermissionInfo.PROTECTION_NORMAL);
6308 bp.pendingInfo = pi;
6309 }
6310 out.put(bp.name, bp);
6311 } else {
6312 reportSettingsProblem(Log.WARN,
6313 "Error in package manager settings: permissions has"
6314 + " no name at " + parser.getPositionDescription());
6315 }
6316 } else {
6317 reportSettingsProblem(Log.WARN,
6318 "Unknown element reading permissions: "
6319 + parser.getName() + " at "
6320 + parser.getPositionDescription());
6321 }
6322 XmlUtils.skipCurrentTag(parser);
6323 }
6324 }
6325
6326 private void readDisabledSysPackageLP(XmlPullParser parser)
6327 throws XmlPullParserException, IOException {
6328 String name = parser.getAttributeValue(null, "name");
6329 String codePathStr = parser.getAttributeValue(null, "codePath");
6330 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6331 if(resourcePathStr == null) {
6332 resourcePathStr = codePathStr;
6333 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006334 String version = parser.getAttributeValue(null, "version");
6335 int versionCode = 0;
6336 if (version != null) {
6337 try {
6338 versionCode = Integer.parseInt(version);
6339 } catch (NumberFormatException e) {
6340 }
6341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342
6343 int pkgFlags = 0;
6344 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6345 PackageSetting ps = new PackageSetting(name,
6346 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006347 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 String timeStampStr = parser.getAttributeValue(null, "ts");
6349 if (timeStampStr != null) {
6350 try {
6351 long timeStamp = Long.parseLong(timeStampStr);
6352 ps.setTimeStamp(timeStamp, timeStampStr);
6353 } catch (NumberFormatException e) {
6354 }
6355 }
6356 String idStr = parser.getAttributeValue(null, "userId");
6357 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6358 if(ps.userId <= 0) {
6359 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6360 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6361 }
6362 int outerDepth = parser.getDepth();
6363 int type;
6364 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6365 && (type != XmlPullParser.END_TAG
6366 || parser.getDepth() > outerDepth)) {
6367 if (type == XmlPullParser.END_TAG
6368 || type == XmlPullParser.TEXT) {
6369 continue;
6370 }
6371
6372 String tagName = parser.getName();
6373 if (tagName.equals("perms")) {
6374 readGrantedPermissionsLP(parser,
6375 ps.grantedPermissions);
6376 } else {
6377 reportSettingsProblem(Log.WARN,
6378 "Unknown element under <updated-package>: "
6379 + parser.getName());
6380 XmlUtils.skipCurrentTag(parser);
6381 }
6382 }
6383 mDisabledSysPackages.put(name, ps);
6384 }
6385
6386 private void readPackageLP(XmlPullParser parser)
6387 throws XmlPullParserException, IOException {
6388 String name = null;
6389 String idStr = null;
6390 String sharedIdStr = null;
6391 String codePathStr = null;
6392 String resourcePathStr = null;
6393 String systemStr = null;
Jacek Surazskic64322c2009-04-28 15:26:38 +02006394 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006395 int pkgFlags = 0;
6396 String timeStampStr;
6397 long timeStamp = 0;
6398 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006399 String version = null;
6400 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 try {
6402 name = parser.getAttributeValue(null, "name");
6403 idStr = parser.getAttributeValue(null, "userId");
6404 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6405 codePathStr = parser.getAttributeValue(null, "codePath");
6406 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006407 version = parser.getAttributeValue(null, "version");
6408 if (version != null) {
6409 try {
6410 versionCode = Integer.parseInt(version);
6411 } catch (NumberFormatException e) {
6412 }
6413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazskic64322c2009-04-28 15:26:38 +02006415 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 if (systemStr != null) {
6417 if ("true".equals(systemStr)) {
6418 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6419 }
6420 } else {
6421 // Old settings that don't specify system... just treat
6422 // them as system, good enough.
6423 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6424 }
6425 timeStampStr = parser.getAttributeValue(null, "ts");
6426 if (timeStampStr != null) {
6427 try {
6428 timeStamp = Long.parseLong(timeStampStr);
6429 } catch (NumberFormatException e) {
6430 }
6431 }
6432 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6433 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6434 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6435 if (resourcePathStr == null) {
6436 resourcePathStr = codePathStr;
6437 }
6438 if (name == null) {
6439 reportSettingsProblem(Log.WARN,
6440 "Error in package manager settings: <package> has no name at "
6441 + parser.getPositionDescription());
6442 } else if (codePathStr == null) {
6443 reportSettingsProblem(Log.WARN,
6444 "Error in package manager settings: <package> has no codePath at "
6445 + parser.getPositionDescription());
6446 } else if (userId > 0) {
6447 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006448 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6450 + ": userId=" + userId + " pkg=" + packageSetting);
6451 if (packageSetting == null) {
6452 reportSettingsProblem(Log.ERROR,
6453 "Failure adding uid " + userId
6454 + " while parsing settings at "
6455 + parser.getPositionDescription());
6456 } else {
6457 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6458 }
6459 } else if (sharedIdStr != null) {
6460 userId = sharedIdStr != null
6461 ? Integer.parseInt(sharedIdStr) : 0;
6462 if (userId > 0) {
6463 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006464 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6466 mPendingPackages.add((PendingPackage) packageSetting);
6467 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6468 + ": sharedUserId=" + userId + " pkg="
6469 + packageSetting);
6470 } else {
6471 reportSettingsProblem(Log.WARN,
6472 "Error in package manager settings: package "
6473 + name + " has bad sharedId " + sharedIdStr
6474 + " at " + parser.getPositionDescription());
6475 }
6476 } else {
6477 reportSettingsProblem(Log.WARN,
6478 "Error in package manager settings: package "
6479 + name + " has bad userId " + idStr + " at "
6480 + parser.getPositionDescription());
6481 }
6482 } catch (NumberFormatException e) {
6483 reportSettingsProblem(Log.WARN,
6484 "Error in package manager settings: package "
6485 + name + " has bad userId " + idStr + " at "
6486 + parser.getPositionDescription());
6487 }
6488 if (packageSetting != null) {
Jacek Surazskic64322c2009-04-28 15:26:38 +02006489 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 final String enabledStr = parser.getAttributeValue(null, "enabled");
6491 if (enabledStr != null) {
6492 if (enabledStr.equalsIgnoreCase("true")) {
6493 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
6494 } else if (enabledStr.equalsIgnoreCase("false")) {
6495 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
6496 } else if (enabledStr.equalsIgnoreCase("default")) {
6497 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6498 } else {
6499 reportSettingsProblem(Log.WARN,
6500 "Error in package manager settings: package "
6501 + name + " has bad enabled value: " + idStr
6502 + " at " + parser.getPositionDescription());
6503 }
6504 } else {
6505 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6506 }
6507 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
6508 if (installStatusStr != null) {
6509 if (installStatusStr.equalsIgnoreCase("false")) {
6510 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
6511 } else {
6512 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
6513 }
6514 }
6515
6516 int outerDepth = parser.getDepth();
6517 int type;
6518 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6519 && (type != XmlPullParser.END_TAG
6520 || parser.getDepth() > outerDepth)) {
6521 if (type == XmlPullParser.END_TAG
6522 || type == XmlPullParser.TEXT) {
6523 continue;
6524 }
6525
6526 String tagName = parser.getName();
6527 if (tagName.equals("disabled-components")) {
6528 readDisabledComponentsLP(packageSetting, parser);
6529 } else if (tagName.equals("enabled-components")) {
6530 readEnabledComponentsLP(packageSetting, parser);
6531 } else if (tagName.equals("sigs")) {
6532 packageSetting.signatures.readXml(parser, mPastSignatures);
6533 } else if (tagName.equals("perms")) {
6534 readGrantedPermissionsLP(parser,
6535 packageSetting.loadedPermissions);
6536 packageSetting.permissionsFixed = true;
6537 } else {
6538 reportSettingsProblem(Log.WARN,
6539 "Unknown element under <package>: "
6540 + parser.getName());
6541 XmlUtils.skipCurrentTag(parser);
6542 }
6543 }
6544 } else {
6545 XmlUtils.skipCurrentTag(parser);
6546 }
6547 }
6548
6549 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
6550 XmlPullParser parser)
6551 throws IOException, XmlPullParserException {
6552 int outerDepth = parser.getDepth();
6553 int type;
6554 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6555 && (type != XmlPullParser.END_TAG
6556 || parser.getDepth() > outerDepth)) {
6557 if (type == XmlPullParser.END_TAG
6558 || type == XmlPullParser.TEXT) {
6559 continue;
6560 }
6561
6562 String tagName = parser.getName();
6563 if (tagName.equals("item")) {
6564 String name = parser.getAttributeValue(null, "name");
6565 if (name != null) {
6566 packageSetting.disabledComponents.add(name.intern());
6567 } else {
6568 reportSettingsProblem(Log.WARN,
6569 "Error in package manager settings: <disabled-components> has"
6570 + " no name at " + parser.getPositionDescription());
6571 }
6572 } else {
6573 reportSettingsProblem(Log.WARN,
6574 "Unknown element under <disabled-components>: "
6575 + parser.getName());
6576 }
6577 XmlUtils.skipCurrentTag(parser);
6578 }
6579 }
6580
6581 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
6582 XmlPullParser parser)
6583 throws IOException, XmlPullParserException {
6584 int outerDepth = parser.getDepth();
6585 int type;
6586 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6587 && (type != XmlPullParser.END_TAG
6588 || parser.getDepth() > outerDepth)) {
6589 if (type == XmlPullParser.END_TAG
6590 || type == XmlPullParser.TEXT) {
6591 continue;
6592 }
6593
6594 String tagName = parser.getName();
6595 if (tagName.equals("item")) {
6596 String name = parser.getAttributeValue(null, "name");
6597 if (name != null) {
6598 packageSetting.enabledComponents.add(name.intern());
6599 } else {
6600 reportSettingsProblem(Log.WARN,
6601 "Error in package manager settings: <enabled-components> has"
6602 + " no name at " + parser.getPositionDescription());
6603 }
6604 } else {
6605 reportSettingsProblem(Log.WARN,
6606 "Unknown element under <enabled-components>: "
6607 + parser.getName());
6608 }
6609 XmlUtils.skipCurrentTag(parser);
6610 }
6611 }
6612
6613 private void readSharedUserLP(XmlPullParser parser)
6614 throws XmlPullParserException, IOException {
6615 String name = null;
6616 String idStr = null;
6617 int pkgFlags = 0;
6618 SharedUserSetting su = null;
6619 try {
6620 name = parser.getAttributeValue(null, "name");
6621 idStr = parser.getAttributeValue(null, "userId");
6622 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6623 if ("true".equals(parser.getAttributeValue(null, "system"))) {
6624 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6625 }
6626 if (name == null) {
6627 reportSettingsProblem(Log.WARN,
6628 "Error in package manager settings: <shared-user> has no name at "
6629 + parser.getPositionDescription());
6630 } else if (userId == 0) {
6631 reportSettingsProblem(Log.WARN,
6632 "Error in package manager settings: shared-user "
6633 + name + " has bad userId " + idStr + " at "
6634 + parser.getPositionDescription());
6635 } else {
6636 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
6637 reportSettingsProblem(Log.ERROR,
6638 "Occurred while parsing settings at "
6639 + parser.getPositionDescription());
6640 }
6641 }
6642 } catch (NumberFormatException e) {
6643 reportSettingsProblem(Log.WARN,
6644 "Error in package manager settings: package "
6645 + name + " has bad userId " + idStr + " at "
6646 + parser.getPositionDescription());
6647 };
6648
6649 if (su != null) {
6650 int outerDepth = parser.getDepth();
6651 int type;
6652 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6653 && (type != XmlPullParser.END_TAG
6654 || parser.getDepth() > outerDepth)) {
6655 if (type == XmlPullParser.END_TAG
6656 || type == XmlPullParser.TEXT) {
6657 continue;
6658 }
6659
6660 String tagName = parser.getName();
6661 if (tagName.equals("sigs")) {
6662 su.signatures.readXml(parser, mPastSignatures);
6663 } else if (tagName.equals("perms")) {
6664 readGrantedPermissionsLP(parser, su.loadedPermissions);
6665 } else {
6666 reportSettingsProblem(Log.WARN,
6667 "Unknown element under <shared-user>: "
6668 + parser.getName());
6669 XmlUtils.skipCurrentTag(parser);
6670 }
6671 }
6672
6673 } else {
6674 XmlUtils.skipCurrentTag(parser);
6675 }
6676 }
6677
6678 private void readGrantedPermissionsLP(XmlPullParser parser,
6679 HashSet<String> outPerms) throws IOException, XmlPullParserException {
6680 int outerDepth = parser.getDepth();
6681 int type;
6682 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6683 && (type != XmlPullParser.END_TAG
6684 || parser.getDepth() > outerDepth)) {
6685 if (type == XmlPullParser.END_TAG
6686 || type == XmlPullParser.TEXT) {
6687 continue;
6688 }
6689
6690 String tagName = parser.getName();
6691 if (tagName.equals("item")) {
6692 String name = parser.getAttributeValue(null, "name");
6693 if (name != null) {
6694 outPerms.add(name.intern());
6695 } else {
6696 reportSettingsProblem(Log.WARN,
6697 "Error in package manager settings: <perms> has"
6698 + " no name at " + parser.getPositionDescription());
6699 }
6700 } else {
6701 reportSettingsProblem(Log.WARN,
6702 "Unknown element under <perms>: "
6703 + parser.getName());
6704 }
6705 XmlUtils.skipCurrentTag(parser);
6706 }
6707 }
6708
6709 private void readPreferredPackagesLP(XmlPullParser parser)
6710 throws XmlPullParserException, IOException {
6711 int outerDepth = parser.getDepth();
6712 int type;
6713 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6714 && (type != XmlPullParser.END_TAG
6715 || parser.getDepth() > outerDepth)) {
6716 if (type == XmlPullParser.END_TAG
6717 || type == XmlPullParser.TEXT) {
6718 continue;
6719 }
6720
6721 String tagName = parser.getName();
6722 if (tagName.equals("item")) {
6723 String name = parser.getAttributeValue(null, "name");
6724 if (name != null) {
6725 mPendingPreferredPackages.add(name);
6726 } else {
6727 reportSettingsProblem(Log.WARN,
6728 "Error in package manager settings: <preferred-package> has no name at "
6729 + parser.getPositionDescription());
6730 }
6731 } else {
6732 reportSettingsProblem(Log.WARN,
6733 "Unknown element under <preferred-packages>: "
6734 + parser.getName());
6735 }
6736 XmlUtils.skipCurrentTag(parser);
6737 }
6738 }
6739
6740 private void readPreferredActivitiesLP(XmlPullParser parser)
6741 throws XmlPullParserException, IOException {
6742 int outerDepth = parser.getDepth();
6743 int type;
6744 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6745 && (type != XmlPullParser.END_TAG
6746 || parser.getDepth() > outerDepth)) {
6747 if (type == XmlPullParser.END_TAG
6748 || type == XmlPullParser.TEXT) {
6749 continue;
6750 }
6751
6752 String tagName = parser.getName();
6753 if (tagName.equals("item")) {
6754 PreferredActivity pa = new PreferredActivity(parser);
6755 if (pa.mParseError == null) {
6756 mPreferredActivities.addFilter(pa);
6757 } else {
6758 reportSettingsProblem(Log.WARN,
6759 "Error in package manager settings: <preferred-activity> "
6760 + pa.mParseError + " at "
6761 + parser.getPositionDescription());
6762 }
6763 } else {
6764 reportSettingsProblem(Log.WARN,
6765 "Unknown element under <preferred-activities>: "
6766 + parser.getName());
6767 XmlUtils.skipCurrentTag(parser);
6768 }
6769 }
6770 }
6771
6772 // Returns -1 if we could not find an available UserId to assign
6773 private int newUserIdLP(Object obj) {
6774 // Let's be stupidly inefficient for now...
6775 final int N = mUserIds.size();
6776 for (int i=0; i<N; i++) {
6777 if (mUserIds.get(i) == null) {
6778 mUserIds.set(i, obj);
6779 return FIRST_APPLICATION_UID + i;
6780 }
6781 }
6782
6783 // None left?
6784 if (N >= MAX_APPLICATION_UIDS) {
6785 return -1;
6786 }
6787
6788 mUserIds.add(obj);
6789 return FIRST_APPLICATION_UID + N;
6790 }
6791
6792 public PackageSetting getDisabledSystemPkg(String name) {
6793 synchronized(mPackages) {
6794 PackageSetting ps = mDisabledSysPackages.get(name);
6795 return ps;
6796 }
6797 }
6798
6799 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
6800 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
6801 if (Config.LOGV) {
6802 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
6803 + " componentName = " + componentInfo.name);
6804 Log.v(TAG, "enabledComponents: "
6805 + Arrays.toString(packageSettings.enabledComponents.toArray()));
6806 Log.v(TAG, "disabledComponents: "
6807 + Arrays.toString(packageSettings.disabledComponents.toArray()));
6808 }
6809 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
6810 || ((componentInfo.enabled
6811 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
6812 || (componentInfo.applicationInfo.enabled
6813 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
6814 && !packageSettings.disabledComponents.contains(componentInfo.name))
6815 || packageSettings.enabledComponents.contains(componentInfo.name));
6816 }
6817 }
6818}