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