blob: 2cf47df57df95bba93437536f9d68cfc7f4ca58b [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!
1951 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1952 // 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
2935 protected void dumpFilter(Printer out, String prefix,
2936 PackageParser.ActivityIntentInfo filter) {
2937 out.println(prefix
2938 + Integer.toHexString(System.identityHashCode(filter.activity))
2939 + " " + filter.activity.component.flattenToShortString());
2940 }
2941
2942// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
2943// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
2944// final List<ResolveInfo> retList = Lists.newArrayList();
2945// while (i.hasNext()) {
2946// final ResolveInfo resolveInfo = i.next();
2947// if (isEnabledLP(resolveInfo.activityInfo)) {
2948// retList.add(resolveInfo);
2949// }
2950// }
2951// return retList;
2952// }
2953
2954 // Keys are String (activity class name), values are Activity.
2955 private final HashMap<ComponentName, PackageParser.Activity> mActivities
2956 = new HashMap<ComponentName, PackageParser.Activity>();
2957 private int mFlags;
2958 }
2959
2960 private final class ServiceIntentResolver
2961 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
2962 public List queryIntent(ContentResolver resolver, Intent intent,
2963 String resolvedType, boolean defaultOnly) {
2964 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2965 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2966 }
2967
2968 public List queryIntent(ContentResolver resolver, Intent intent,
2969 String resolvedType, int flags) {
2970 mFlags = flags;
2971 return super.queryIntent(
2972 resolver, intent, resolvedType,
2973 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2974 }
2975
2976 public final void addService(PackageParser.Service s) {
2977 mServices.put(s.component, s);
2978 if (SHOW_INFO || Config.LOGV) Log.v(
2979 TAG, " " + (s.info.nonLocalizedLabel != null
2980 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2981 if (SHOW_INFO || Config.LOGV) Log.v(
2982 TAG, " Class=" + s.info.name);
2983 int NI = s.intents.size();
2984 int j;
2985 for (j=0; j<NI; j++) {
2986 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
2987 if (SHOW_INFO || Config.LOGV) {
2988 Log.v(TAG, " IntentFilter:");
2989 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2990 }
2991 if (!intent.debugCheck()) {
2992 Log.w(TAG, "==> For Service " + s.info.name);
2993 }
2994 addFilter(intent);
2995 }
2996 }
2997
2998 public final void removeService(PackageParser.Service s) {
2999 mServices.remove(s.component);
3000 if (SHOW_INFO || Config.LOGV) Log.v(
3001 TAG, " " + (s.info.nonLocalizedLabel != null
3002 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3003 if (SHOW_INFO || Config.LOGV) Log.v(
3004 TAG, " Class=" + s.info.name);
3005 int NI = s.intents.size();
3006 int j;
3007 for (j=0; j<NI; j++) {
3008 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3009 if (SHOW_INFO || Config.LOGV) {
3010 Log.v(TAG, " IntentFilter:");
3011 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3012 }
3013 removeFilter(intent);
3014 }
3015 }
3016
3017 @Override
3018 protected boolean allowFilterResult(
3019 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3020 ServiceInfo filterSi = filter.service.info;
3021 for (int i=dest.size()-1; i>=0; i--) {
3022 ServiceInfo destAi = dest.get(i).serviceInfo;
3023 if (destAi.name == filterSi.name
3024 && destAi.packageName == filterSi.packageName) {
3025 return false;
3026 }
3027 }
3028 return true;
3029 }
3030
3031 @Override
3032 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3033 int match) {
3034 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3035 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3036 return null;
3037 }
3038 final PackageParser.Service service = info.service;
3039 if (mSafeMode && (service.info.applicationInfo.flags
3040 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3041 return null;
3042 }
3043 final ResolveInfo res = new ResolveInfo();
3044 res.serviceInfo = PackageParser.generateServiceInfo(service,
3045 mFlags);
3046 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3047 res.filter = filter;
3048 }
3049 res.priority = info.getPriority();
3050 res.preferredOrder = service.owner.mPreferredOrder;
3051 //System.out.println("Result: " + res.activityInfo.className +
3052 // " = " + res.priority);
3053 res.match = match;
3054 res.isDefault = info.hasDefault;
3055 res.labelRes = info.labelRes;
3056 res.nonLocalizedLabel = info.nonLocalizedLabel;
3057 res.icon = info.icon;
3058 return res;
3059 }
3060
3061 @Override
3062 protected void sortResults(List<ResolveInfo> results) {
3063 Collections.sort(results, mResolvePrioritySorter);
3064 }
3065
3066 @Override
3067 protected void dumpFilter(Printer out, String prefix,
3068 PackageParser.ServiceIntentInfo filter) {
3069 out.println(prefix
3070 + Integer.toHexString(System.identityHashCode(filter.service))
3071 + " " + filter.service.component.flattenToShortString());
3072 }
3073
3074// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3075// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3076// final List<ResolveInfo> retList = Lists.newArrayList();
3077// while (i.hasNext()) {
3078// final ResolveInfo resolveInfo = (ResolveInfo) i;
3079// if (isEnabledLP(resolveInfo.serviceInfo)) {
3080// retList.add(resolveInfo);
3081// }
3082// }
3083// return retList;
3084// }
3085
3086 // Keys are String (activity class name), values are Activity.
3087 private final HashMap<ComponentName, PackageParser.Service> mServices
3088 = new HashMap<ComponentName, PackageParser.Service>();
3089 private int mFlags;
3090 };
3091
3092 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3093 new Comparator<ResolveInfo>() {
3094 public int compare(ResolveInfo r1, ResolveInfo r2) {
3095 int v1 = r1.priority;
3096 int v2 = r2.priority;
3097 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3098 if (v1 != v2) {
3099 return (v1 > v2) ? -1 : 1;
3100 }
3101 v1 = r1.preferredOrder;
3102 v2 = r2.preferredOrder;
3103 if (v1 != v2) {
3104 return (v1 > v2) ? -1 : 1;
3105 }
3106 if (r1.isDefault != r2.isDefault) {
3107 return r1.isDefault ? -1 : 1;
3108 }
3109 v1 = r1.match;
3110 v2 = r2.match;
3111 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3112 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3113 }
3114 };
3115
3116 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3117 new Comparator<ProviderInfo>() {
3118 public int compare(ProviderInfo p1, ProviderInfo p2) {
3119 final int v1 = p1.initOrder;
3120 final int v2 = p2.initOrder;
3121 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3122 }
3123 };
3124
3125 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3126 IActivityManager am = ActivityManagerNative.getDefault();
3127 if (am != null) {
3128 try {
3129 final Intent intent = new Intent(action,
3130 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3131 if (extras != null) {
3132 intent.putExtras(extras);
3133 }
3134 am.broadcastIntent(
3135 null, intent,
3136 null, null, 0, null, null, null, false, false);
3137 } catch (RemoteException ex) {
3138 }
3139 }
3140 }
3141
3142 private final class AppDirObserver extends FileObserver {
3143 public AppDirObserver(String path, int mask, boolean isrom) {
3144 super(path, mask);
3145 mRootDir = path;
3146 mIsRom = isrom;
3147 }
3148
3149 public void onEvent(int event, String path) {
3150 String removedPackage = null;
3151 int removedUid = -1;
3152 String addedPackage = null;
3153 int addedUid = -1;
3154
3155 synchronized (mInstallLock) {
3156 String fullPathStr = null;
3157 File fullPath = null;
3158 if (path != null) {
3159 fullPath = new File(mRootDir, path);
3160 fullPathStr = fullPath.getPath();
3161 }
3162
3163 if (Config.LOGV) Log.v(
3164 TAG, "File " + fullPathStr + " changed: "
3165 + Integer.toHexString(event));
3166
3167 if (!isPackageFilename(path)) {
3168 if (Config.LOGV) Log.v(
3169 TAG, "Ignoring change of non-package file: " + fullPathStr);
3170 return;
3171 }
3172
3173 if ((event&REMOVE_EVENTS) != 0) {
3174 synchronized (mInstallLock) {
3175 PackageParser.Package p = mAppDirs.get(fullPathStr);
3176 if (p != null) {
3177 removePackageLI(p, true);
3178 removedPackage = p.applicationInfo.packageName;
3179 removedUid = p.applicationInfo.uid;
3180 }
3181 }
3182 }
3183
3184 if ((event&ADD_EVENTS) != 0) {
3185 PackageParser.Package p = mAppDirs.get(fullPathStr);
3186 if (p == null) {
3187 p = scanPackageLI(fullPath, fullPath, fullPath,
3188 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3189 PackageParser.PARSE_CHATTY |
3190 PackageParser.PARSE_MUST_BE_APK,
3191 SCAN_MONITOR);
3192 if (p != null) {
3193 synchronized (mPackages) {
3194 grantPermissionsLP(p, false);
3195 }
3196 addedPackage = p.applicationInfo.packageName;
3197 addedUid = p.applicationInfo.uid;
3198 }
3199 }
3200 }
3201
3202 synchronized (mPackages) {
3203 mSettings.writeLP();
3204 }
3205 }
3206
3207 if (removedPackage != null) {
3208 Bundle extras = new Bundle(1);
3209 extras.putInt(Intent.EXTRA_UID, removedUid);
3210 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3211 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3212 }
3213 if (addedPackage != null) {
3214 Bundle extras = new Bundle(1);
3215 extras.putInt(Intent.EXTRA_UID, addedUid);
3216 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3217 }
3218 }
3219
3220 private final String mRootDir;
3221 private final boolean mIsRom;
3222 }
3223
3224 /* Called when a downloaded package installation has been confirmed by the user */
3225 public void installPackage(
3226 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
3227 mContext.enforceCallingOrSelfPermission(
3228 android.Manifest.permission.INSTALL_PACKAGES, null);
3229
3230 // Queue up an async operation since the package installation may take a little while.
3231 mHandler.post(new Runnable() {
3232 public void run() {
3233 mHandler.removeCallbacks(this);
3234 PackageInstalledInfo res;
3235 synchronized (mInstallLock) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003236 res = installPackageLI(packageURI, flags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 }
3238 if (observer != null) {
3239 try {
3240 observer.packageInstalled(res.name, res.returnCode);
3241 } catch (RemoteException e) {
3242 Log.i(TAG, "Observer no longer exists.");
3243 }
3244 }
3245 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3246 // call appears in the synchronized block above.
3247 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3248 res.removedInfo.sendBroadcast(false, true);
3249 Bundle extras = new Bundle(1);
3250 extras.putInt(Intent.EXTRA_UID, res.uid);
3251 if (res.removedInfo.removedPackage != null) {
3252 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3253 }
3254 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3255 res.pkg.applicationInfo.packageName,
3256 extras);
3257 }
3258 Runtime.getRuntime().gc();
3259 }
3260 });
3261 }
3262
3263 class PackageInstalledInfo {
3264 String name;
3265 int uid;
3266 PackageParser.Package pkg;
3267 int returnCode;
3268 PackageRemovedInfo removedInfo;
3269 }
3270
3271 /*
3272 * Install a non-existing package.
3273 */
3274 private void installNewPackageLI(String pkgName,
3275 File tmpPackageFile,
3276 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003277 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 PackageInstalledInfo res) {
3279 // Remember this for later, in case we need to rollback this install
3280 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3281 res.name = pkgName;
3282 synchronized(mPackages) {
3283 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3284 // Don't allow installation over an existing package with the same name.
3285 Log.w(TAG, "Attempt to re-install " + pkgName
3286 + " without first uninstalling.");
3287 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3288 return;
3289 }
3290 }
3291 if (destPackageFile.exists()) {
3292 // It's safe to do this because we know (from the above check) that the file
3293 // isn't currently used for an installed package.
3294 destPackageFile.delete();
3295 }
3296 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3297 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3298 destResourceFile, pkg, 0,
3299 SCAN_MONITOR | SCAN_FORCE_DEX
3300 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003301 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3302 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 if (newPackage == null) {
3304 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3305 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3306 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3307 }
3308 } else {
3309 updateSettingsLI(pkgName, tmpPackageFile,
3310 destFilePath, destPackageFile,
3311 destResourceFile, pkg,
3312 newPackage,
3313 true,
3314 forwardLocked,
3315 res);
3316 // delete the partially installed application. the data directory will have to be
3317 // restored if it was already existing
3318 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3319 // remove package from internal structures. Note that we want deletePackageX to
3320 // delete the package data and cache directories that it created in
3321 // scanPackageLocked, unless those directories existed before we even tried to
3322 // install.
3323 deletePackageLI(
3324 pkgName, true,
3325 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3326 res.removedInfo);
3327 }
3328 }
3329 }
3330
3331 private void replacePackageLI(String pkgName,
3332 File tmpPackageFile,
3333 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003334 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 PackageInstalledInfo res) {
3336 PackageParser.Package deletedPackage;
3337 // First find the old package info and check signatures
3338 synchronized(mPackages) {
3339 deletedPackage = mPackages.get(pkgName);
3340 if(checkSignaturesLP(pkg, deletedPackage) != PackageManager.SIGNATURE_MATCH) {
3341 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3342 return;
3343 }
3344 }
3345 boolean sysPkg = ((deletedPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
3346 if(sysPkg) {
3347 replaceSystemPackageLI(deletedPackage,
3348 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003349 destPackageFile, destResourceFile, pkg, forwardLocked,
3350 newInstall, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 } else {
3352 replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003353 destPackageFile, destResourceFile, pkg, forwardLocked,
3354 newInstall, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 }
3356 }
3357
3358 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3359 File tmpPackageFile,
3360 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003361 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 PackageInstalledInfo res) {
3363 PackageParser.Package newPackage = null;
3364 String pkgName = deletedPackage.packageName;
3365 boolean deletedPkg = true;
3366 boolean updatedSettings = false;
3367 int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
3368 // First delete the existing package while retaining the data directory
3369 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3370 res.removedInfo)) {
3371 // If the existing package was'nt successfully deleted
3372 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3373 deletedPkg = false;
3374 } else {
3375 // Successfully deleted the old package. Now proceed with re-installation
3376 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3377 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3378 destResourceFile, pkg, parseFlags,
3379 SCAN_MONITOR | SCAN_FORCE_DEX
3380 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003381 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3382 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 if (newPackage == null) {
3384 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3385 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3386 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3387 }
3388 } else {
3389 updateSettingsLI(pkgName, tmpPackageFile,
3390 destFilePath, destPackageFile,
3391 destResourceFile, pkg,
3392 newPackage,
3393 true,
3394 forwardLocked,
3395 res);
3396 updatedSettings = true;
3397 }
3398 }
3399
3400 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3401 // If we deleted an exisiting package, the old source and resource files that we
3402 // were keeping around in case we needed them (see below) can now be deleted
3403 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3404 final ApplicationInfo installedPackageAppInfo =
3405 newPackage.applicationInfo;
3406 if (!deletedPackageAppInfo.sourceDir
3407 .equals(installedPackageAppInfo.sourceDir)) {
3408 new File(deletedPackageAppInfo.sourceDir).delete();
3409 }
3410 if (!deletedPackageAppInfo.publicSourceDir
3411 .equals(installedPackageAppInfo.publicSourceDir)) {
3412 new File(deletedPackageAppInfo.publicSourceDir).delete();
3413 }
3414 //update signature on the new package setting
3415 //this should always succeed, since we checked the
3416 //signature earlier.
3417 synchronized(mPackages) {
3418 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3419 parseFlags, true);
3420 }
3421 } else {
3422 // remove package from internal structures. Note that we want deletePackageX to
3423 // delete the package data and cache directories that it created in
3424 // scanPackageLocked, unless those directories existed before we even tried to
3425 // install.
3426 if(updatedSettings) {
3427 deletePackageLI(
3428 pkgName, true,
3429 PackageManager.DONT_DELETE_DATA,
3430 res.removedInfo);
3431 }
3432 // Since we failed to install the new package we need to restore the old
3433 // package that we deleted.
3434 if(deletedPkg) {
3435 installPackageLI(
3436 Uri.fromFile(new File(deletedPackage.mPath)),
3437 isForwardLocked(deletedPackage)
3438 ? PackageManager.FORWARD_LOCK_PACKAGE
The Android Open Source Project10592532009-03-18 17:39:46 -07003439 : 0, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 }
3441 }
3442 }
3443
3444 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3445 File tmpPackageFile,
3446 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003447 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 PackageInstalledInfo res) {
3449 PackageParser.Package newPackage = null;
3450 boolean updatedSettings = false;
3451 int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
3452 PackageParser.PARSE_IS_SYSTEM;
3453 String packageName = deletedPackage.packageName;
3454 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3455 if (packageName == null) {
3456 Log.w(TAG, "Attempt to delete null packageName.");
3457 return;
3458 }
3459 PackageParser.Package oldPkg;
3460 PackageSetting oldPkgSetting;
3461 synchronized (mPackages) {
3462 oldPkg = mPackages.get(packageName);
3463 oldPkgSetting = mSettings.mPackages.get(packageName);
3464 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3465 (oldPkgSetting == null)) {
3466 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3467 return;
3468 }
3469 }
3470 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3471 res.removedInfo.removedPackage = packageName;
3472 // Remove existing system package
3473 removePackageLI(oldPkg, true);
3474 synchronized (mPackages) {
3475 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3476 }
3477
3478 // Successfully disabled the old package. Now proceed with re-installation
3479 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3480 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3481 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3482 destResourceFile, pkg, parseFlags,
3483 SCAN_MONITOR | SCAN_FORCE_DEX
3484 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003485 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3486 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 if (newPackage == null) {
3488 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3489 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3490 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3491 }
3492 } else {
3493 updateSettingsLI(packageName, tmpPackageFile,
3494 destFilePath, destPackageFile,
3495 destResourceFile, pkg,
3496 newPackage,
3497 true,
3498 forwardLocked,
3499 res);
3500 updatedSettings = true;
3501 }
3502
3503 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3504 //update signature on the new package setting
3505 //this should always succeed, since we checked the
3506 //signature earlier.
3507 synchronized(mPackages) {
3508 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3509 parseFlags, true);
3510 }
3511 } else {
3512 // Re installation failed. Restore old information
3513 // Remove new pkg information
3514 removePackageLI(newPackage, true);
3515 // Add back the old system package
3516 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3517 oldPkgSetting.resourcePath,
3518 oldPkg, parseFlags,
3519 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003520 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 // Restore the old system information in Settings
3522 synchronized(mPackages) {
3523 if(updatedSettings) {
3524 mSettings.enableSystemPackageLP(packageName);
3525 }
3526 mSettings.writeLP();
3527 }
3528 }
3529 }
3530
3531 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3532 String destFilePath, File destPackageFile,
3533 File destResourceFile,
3534 PackageParser.Package pkg,
3535 PackageParser.Package newPackage,
3536 boolean replacingExistingPackage,
3537 boolean forwardLocked,
3538 PackageInstalledInfo res) {
3539 synchronized (mPackages) {
3540 //write settings. the installStatus will be incomplete at this stage.
3541 //note that the new package setting would have already been
3542 //added to mPackages. It hasn't been persisted yet.
3543 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3544 mSettings.writeLP();
3545 }
3546
3547 int retCode = 0;
3548 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3549 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3550 destPackageFile.toString());
3551 if (retCode != 0) {
3552 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3553 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3554 return;
3555 }
3556 }
3557 // XXX There are probably some big issues here: upon doing
3558 // the rename, we have reached the point of no return (the
3559 // original .apk is gone!), so we can't fail. Yet... we can.
3560 if (!tmpPackageFile.renameTo(destPackageFile)) {
3561 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3562 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3563 } else {
3564 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
3565 destResourceFile,
3566 forwardLocked);
3567 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3568 return;
3569 } else {
3570 Log.d(TAG, "New package installed in " + destPackageFile);
3571 }
3572 }
3573 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3574 if (mInstaller != null) {
3575 mInstaller.rmdex(tmpPackageFile.getPath());
3576 }
3577 }
3578
3579 synchronized (mPackages) {
3580 grantPermissionsLP(newPackage, true);
3581 res.name = pkgName;
3582 res.uid = newPackage.applicationInfo.uid;
3583 res.pkg = newPackage;
3584 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
3585 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3586 //to update install status
3587 mSettings.writeLP();
3588 }
3589 }
3590
The Android Open Source Project10592532009-03-18 17:39:46 -07003591 private PackageInstalledInfo installPackageLI(Uri pPackageURI,
3592 int pFlags, boolean newInstall) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 File tmpPackageFile = null;
3594 String pkgName = null;
3595 boolean forwardLocked = false;
3596 boolean replacingExistingPackage = false;
3597 // Result object to be returned
3598 PackageInstalledInfo res = new PackageInstalledInfo();
3599 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3600 res.uid = -1;
3601 res.pkg = null;
3602 res.removedInfo = new PackageRemovedInfo();
3603
3604 main_flow: try {
3605 tmpPackageFile = createTempPackageFile();
3606 if (tmpPackageFile == null) {
3607 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3608 break main_flow;
3609 }
3610 tmpPackageFile.deleteOnExit(); // paranoia
3611 if (pPackageURI.getScheme().equals("file")) {
3612 final File srcPackageFile = new File(pPackageURI.getPath());
3613 // We copy the source package file to a temp file and then rename it to the
3614 // destination file in order to eliminate a window where the package directory
3615 // scanner notices the new package file but it's not completely copied yet.
3616 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3617 Log.e(TAG, "Couldn't copy package file to temp file.");
3618 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3619 break main_flow;
3620 }
3621 } else if (pPackageURI.getScheme().equals("content")) {
3622 ParcelFileDescriptor fd;
3623 try {
3624 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
3625 } catch (FileNotFoundException e) {
3626 Log.e(TAG, "Couldn't open file descriptor from download service.");
3627 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3628 break main_flow;
3629 }
3630 if (fd == null) {
3631 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3632 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3633 break main_flow;
3634 }
3635 if (Config.LOGV) {
3636 Log.v(TAG, "Opened file descriptor from download service.");
3637 }
3638 ParcelFileDescriptor.AutoCloseInputStream
3639 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3640 // We copy the source package file to a temp file and then rename it to the
3641 // destination file in order to eliminate a window where the package directory
3642 // scanner notices the new package file but it's not completely copied yet.
3643 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3644 Log.e(TAG, "Couldn't copy package stream to temp file.");
3645 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3646 break main_flow;
3647 }
3648 } else {
3649 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
3650 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3651 break main_flow;
3652 }
3653 pkgName = PackageParser.parsePackageName(
3654 tmpPackageFile.getAbsolutePath(), 0);
3655 if (pkgName == null) {
3656 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3657 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3658 break main_flow;
3659 }
3660 res.name = pkgName;
3661 //initialize some variables before installing pkg
3662 final String pkgFileName = pkgName + ".apk";
3663 final File destDir = ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
3664 ? mDrmAppPrivateInstallDir
3665 : mAppInstallDir;
3666 final File destPackageFile = new File(destDir, pkgFileName);
3667 final String destFilePath = destPackageFile.getAbsolutePath();
3668 File destResourceFile;
3669 if ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
3670 final String publicZipFileName = pkgName + ".zip";
3671 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3672 forwardLocked = true;
3673 } else {
3674 destResourceFile = destPackageFile;
3675 }
3676 // Retrieve PackageSettings and parse package
3677 int parseFlags = PackageParser.PARSE_CHATTY;
3678 parseFlags |= mDefParseFlags;
3679 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3680 pp.setSeparateProcesses(mSeparateProcesses);
3681 pp.setSdkVersion(mSdkVersion);
3682 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3683 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3684 if (pkg == null) {
3685 res.returnCode = pp.getParseError();
3686 break main_flow;
3687 }
3688 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3689 res.returnCode = pp.getParseError();
3690 break main_flow;
3691 }
3692
3693 synchronized (mPackages) {
3694 //check if installing already existing package
3695 if ((pFlags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
3696 && mPackages.containsKey(pkgName)) {
3697 replacingExistingPackage = true;
3698 }
3699 }
3700
3701 if(replacingExistingPackage) {
3702 replacePackageLI(pkgName,
3703 tmpPackageFile,
3704 destFilePath, destPackageFile, destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003705 pkg, forwardLocked, newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 res);
3707 } else {
3708 installNewPackageLI(pkgName,
3709 tmpPackageFile,
3710 destFilePath, destPackageFile, destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003711 pkg, forwardLocked, newInstall,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 res);
3713 }
3714 } finally {
3715 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3716 tmpPackageFile.delete();
3717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003719 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 }
3721
3722 private int setPermissionsLI(String pkgName,
3723 PackageParser.Package newPackage,
3724 String destFilePath,
3725 File destResourceFile,
3726 boolean forwardLocked) {
3727 int retCode;
3728 if (forwardLocked) {
3729 try {
3730 extractPublicFiles(newPackage, destResourceFile);
3731 } catch (IOException e) {
3732 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3733 " forward-locked app.");
3734 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3735 } finally {
3736 //TODO clean up the extracted public files
3737 }
3738 if (mInstaller != null) {
3739 retCode = mInstaller.setForwardLockPerm(pkgName,
3740 newPackage.applicationInfo.uid);
3741 } else {
3742 final int filePermissions =
3743 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3744 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3745 newPackage.applicationInfo.uid);
3746 }
3747 } else {
3748 final int filePermissions =
3749 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3750 |FileUtils.S_IROTH;
3751 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3752 }
3753 if (retCode != 0) {
3754 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3755 + ". The return code was: " + retCode);
3756 }
3757 return PackageManager.INSTALL_SUCCEEDED;
3758 }
3759
3760 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3761 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3762 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3763 }
3764
3765 private void extractPublicFiles(PackageParser.Package newPackage,
3766 File publicZipFile) throws IOException {
3767 final ZipOutputStream publicZipOutStream =
3768 new ZipOutputStream(new FileOutputStream(publicZipFile));
3769 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3770
3771 // Copy manifest, resources.arsc and res directory to public zip
3772
3773 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3774 while (privateZipEntries.hasMoreElements()) {
3775 final ZipEntry zipEntry = privateZipEntries.nextElement();
3776 final String zipEntryName = zipEntry.getName();
3777 if ("AndroidManifest.xml".equals(zipEntryName)
3778 || "resources.arsc".equals(zipEntryName)
3779 || zipEntryName.startsWith("res/")) {
3780 try {
3781 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3782 } catch (IOException e) {
3783 try {
3784 publicZipOutStream.close();
3785 throw e;
3786 } finally {
3787 publicZipFile.delete();
3788 }
3789 }
3790 }
3791 }
3792
3793 publicZipOutStream.close();
3794 FileUtils.setPermissions(
3795 publicZipFile.getAbsolutePath(),
3796 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
3797 -1, -1);
3798 }
3799
3800 private static void copyZipEntry(ZipEntry zipEntry,
3801 ZipFile inZipFile,
3802 ZipOutputStream outZipStream) throws IOException {
3803 byte[] buffer = new byte[4096];
3804 int num;
3805
3806 ZipEntry newEntry;
3807 if (zipEntry.getMethod() == ZipEntry.STORED) {
3808 // Preserve the STORED method of the input entry.
3809 newEntry = new ZipEntry(zipEntry);
3810 } else {
3811 // Create a new entry so that the compressed len is recomputed.
3812 newEntry = new ZipEntry(zipEntry.getName());
3813 }
3814 outZipStream.putNextEntry(newEntry);
3815
3816 InputStream data = inZipFile.getInputStream(zipEntry);
3817 while ((num = data.read(buffer)) > 0) {
3818 outZipStream.write(buffer, 0, num);
3819 }
3820 outZipStream.flush();
3821 }
3822
3823 private void deleteTempPackageFiles() {
3824 FilenameFilter filter = new FilenameFilter() {
3825 public boolean accept(File dir, String name) {
3826 return name.startsWith("vmdl") && name.endsWith(".tmp");
3827 }
3828 };
3829 String tmpFilesList[] = mAppInstallDir.list(filter);
3830 if(tmpFilesList == null) {
3831 return;
3832 }
3833 for(int i = 0; i < tmpFilesList.length; i++) {
3834 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
3835 tmpFile.delete();
3836 }
3837 }
3838
3839 private File createTempPackageFile() {
3840 File tmpPackageFile;
3841 try {
3842 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
3843 } catch (IOException e) {
3844 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
3845 return null;
3846 }
3847 try {
3848 FileUtils.setPermissions(
3849 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
3850 -1, -1);
3851 } catch (IOException e) {
3852 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
3853 return null;
3854 }
3855 return tmpPackageFile;
3856 }
3857
3858 public void deletePackage(final String packageName,
3859 final IPackageDeleteObserver observer,
3860 final int flags) {
3861 mContext.enforceCallingOrSelfPermission(
3862 android.Manifest.permission.DELETE_PACKAGES, null);
3863 // Queue up an async operation since the package deletion may take a little while.
3864 mHandler.post(new Runnable() {
3865 public void run() {
3866 mHandler.removeCallbacks(this);
3867 final boolean succeded = deletePackageX(packageName, true, true, flags);
3868 if (observer != null) {
3869 try {
3870 observer.packageDeleted(succeded);
3871 } catch (RemoteException e) {
3872 Log.i(TAG, "Observer no longer exists.");
3873 } //end catch
3874 } //end if
3875 } //end run
3876 });
3877 }
3878
3879 /**
3880 * This method is an internal method that could be get invoked either
3881 * to delete an installed package or to clean up a failed installation.
3882 * After deleting an installed package, a broadcast is sent to notify any
3883 * listeners that the package has been installed. For cleaning up a failed
3884 * installation, the broadcast is not necessary since the package's
3885 * installation wouldn't have sent the initial broadcast either
3886 * The key steps in deleting a package are
3887 * deleting the package information in internal structures like mPackages,
3888 * deleting the packages base directories through installd
3889 * updating mSettings to reflect current status
3890 * persisting settings for later use
3891 * sending a broadcast if necessary
3892 */
3893
3894 private boolean deletePackageX(String packageName, boolean sendBroadCast,
3895 boolean deleteCodeAndResources, int flags) {
3896 PackageRemovedInfo info = new PackageRemovedInfo();
3897 boolean res = false;
3898
3899 synchronized (mInstallLock) {
3900 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
3901 }
3902
3903 if(res && sendBroadCast) {
3904 info.sendBroadcast(deleteCodeAndResources, false);
3905 }
3906 return res;
3907 }
3908
3909 static class PackageRemovedInfo {
3910 String removedPackage;
3911 int uid = -1;
3912 int removedUid = -1;
3913
3914 void sendBroadcast(boolean fullRemove, boolean replacing) {
3915 Bundle extras = new Bundle(1);
3916 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
3917 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
3918 if (replacing) {
3919 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3920 }
3921 if (removedPackage != null) {
3922 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3923 }
3924 if (removedUid >= 0) {
3925 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
3926 }
3927 }
3928 }
3929
3930 /*
3931 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
3932 * flag is not set, the data directory is removed as well.
3933 * make sure this flag is set for partially installed apps. If not its meaningless to
3934 * delete a partially installed application.
3935 */
3936 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
3937 int flags) {
3938 String packageName = p.packageName;
3939 outInfo.removedPackage = packageName;
3940 removePackageLI(p, true);
3941 // Retrieve object to delete permissions for shared user later on
3942 PackageSetting deletedPs;
3943 synchronized (mPackages) {
3944 deletedPs = mSettings.mPackages.get(packageName);
3945 }
3946 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
3947 if (mInstaller != null) {
3948 int retCode = mInstaller.remove(packageName);
3949 if (retCode < 0) {
3950 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
3951 + packageName + ", retcode=" + retCode);
3952 // we don't consider this to be a failure of the core package deletion
3953 }
3954 } else {
3955 //for emulator
3956 PackageParser.Package pkg = mPackages.get(packageName);
3957 File dataDir = new File(pkg.applicationInfo.dataDir);
3958 dataDir.delete();
3959 }
3960 synchronized (mPackages) {
3961 outInfo.removedUid = mSettings.removePackageLP(packageName);
3962 }
3963 }
3964 synchronized (mPackages) {
3965 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
3966 // remove permissions associated with package
3967 mSettings.updateSharedUserPerms (deletedPs);
3968 }
3969 // Save settings now
3970 mSettings.writeLP ();
3971 }
3972 }
3973
3974 /*
3975 * Tries to delete system package.
3976 */
3977 private boolean deleteSystemPackageLI(PackageParser.Package p,
3978 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
3979 ApplicationInfo applicationInfo = p.applicationInfo;
3980 //applicable for non-partially installed applications only
3981 if (applicationInfo == null) {
3982 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
3983 return false;
3984 }
3985 PackageSetting ps = null;
3986 // Confirm if the system package has been updated
3987 // An updated system app can be deleted. This will also have to restore
3988 // the system pkg from system partition
3989 synchronized (mPackages) {
3990 ps = mSettings.getDisabledSystemPkg(p.packageName);
3991 }
3992 if (ps == null) {
3993 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
3994 return false;
3995 } else {
3996 Log.i(TAG, "Deleting system pkg from data partition");
3997 }
3998 // Delete the updated package
3999 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4000 if (!ret) {
4001 return false;
4002 }
4003 synchronized (mPackages) {
4004 // Reinstate the old system package
4005 mSettings.enableSystemPackageLP(p.packageName);
4006 }
4007 // Install the system package
4008 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4009 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4010 SCAN_MONITOR);
4011
4012 if (newPkg == null) {
4013 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4014 return false;
4015 }
4016 synchronized (mPackages) {
4017 mSettings.writeLP();
4018 }
4019 return true;
4020 }
4021
4022 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4023 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4024 ApplicationInfo applicationInfo = p.applicationInfo;
4025 if (applicationInfo == null) {
4026 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4027 return false;
4028 }
4029 // Delete application's source directory
4030 File sourceFile = new File(applicationInfo.sourceDir);
4031 if (!sourceFile.exists()) {
4032 Log.w(TAG, "Package source " + applicationInfo.sourceDir + " does not exist.");
4033 }
4034 outInfo.uid = applicationInfo.uid;
4035
4036 // Delete package data from internal structures and also remove data if flag is set
4037 removePackageDataLI(p, outInfo, flags);
4038
4039 // Delete application code and resources
4040 if (deleteCodeAndResources) {
4041 sourceFile.delete();
4042 final File publicSourceFile = new File(applicationInfo.publicSourceDir);
4043 if (publicSourceFile.exists()) {
4044 publicSourceFile.delete();
4045 }
4046 if (mInstaller != null) {
4047 int retCode = mInstaller.rmdex(sourceFile.toString());
4048 if (retCode < 0) {
4049 Log.w(TAG, "Couldn't remove dex file for package: "
4050 + p.packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4051 // we don't consider this to be a failure of the core package deletion
4052 }
4053 }
4054 }
4055 return true;
4056 }
4057
4058 /*
4059 * This method handles package deletion in general
4060 */
4061 private boolean deletePackageLI(String packageName,
4062 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4063 if (packageName == null) {
4064 Log.w(TAG, "Attempt to delete null packageName.");
4065 return false;
4066 }
4067 PackageParser.Package p;
4068 boolean dataOnly = false;
4069 synchronized (mPackages) {
4070 p = mPackages.get(packageName);
4071 if (p == null) {
4072 //this retrieves partially installed apps
4073 dataOnly = true;
4074 PackageSetting ps = mSettings.mPackages.get(packageName);
4075 if (ps == null) {
4076 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4077 return false;
4078 }
4079 p = ps.pkg;
4080 }
4081 }
4082 if (p == null) {
4083 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4084 return false;
4085 }
4086
4087 if (dataOnly) {
4088 // Delete application data first
4089 removePackageDataLI(p, outInfo, flags);
4090 return true;
4091 }
4092 // At this point the package should have ApplicationInfo associated with it
4093 if (p.applicationInfo == null) {
4094 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4095 return false;
4096 }
4097 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4098 Log.i(TAG, "Removing system package:"+p.packageName);
4099 // When an updated system application is deleted we delete the existing resources as well and
4100 // fall back to existing code in system partition
4101 return deleteSystemPackageLI(p, true, flags, outInfo);
4102 }
4103 Log.i(TAG, "Removing non-system package:"+p.packageName);
4104 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4105 }
4106
4107 public void clearApplicationUserData(final String packageName,
4108 final IPackageDataObserver observer) {
4109 mContext.enforceCallingOrSelfPermission(
4110 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4111 // Queue up an async operation since the package deletion may take a little while.
4112 mHandler.post(new Runnable() {
4113 public void run() {
4114 mHandler.removeCallbacks(this);
4115 final boolean succeeded;
4116 synchronized (mInstallLock) {
4117 succeeded = clearApplicationUserDataLI(packageName);
4118 }
4119 if (succeeded) {
4120 // invoke DeviceStorageMonitor's update method to clear any notifications
4121 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4122 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4123 if (dsm != null) {
4124 dsm.updateMemory();
4125 }
4126 }
4127 if(observer != null) {
4128 try {
4129 observer.onRemoveCompleted(packageName, succeeded);
4130 } catch (RemoteException e) {
4131 Log.i(TAG, "Observer no longer exists.");
4132 }
4133 } //end if observer
4134 } //end run
4135 });
4136 }
4137
4138 private boolean clearApplicationUserDataLI(String packageName) {
4139 if (packageName == null) {
4140 Log.w(TAG, "Attempt to delete null packageName.");
4141 return false;
4142 }
4143 PackageParser.Package p;
4144 boolean dataOnly = false;
4145 synchronized (mPackages) {
4146 p = mPackages.get(packageName);
4147 if(p == null) {
4148 dataOnly = true;
4149 PackageSetting ps = mSettings.mPackages.get(packageName);
4150 if((ps == null) || (ps.pkg == null)) {
4151 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4152 return false;
4153 }
4154 p = ps.pkg;
4155 }
4156 }
4157 if(!dataOnly) {
4158 //need to check this only for fully installed applications
4159 if (p == null) {
4160 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4161 return false;
4162 }
4163 final ApplicationInfo applicationInfo = p.applicationInfo;
4164 if (applicationInfo == null) {
4165 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4166 return false;
4167 }
4168 }
4169 if (mInstaller != null) {
4170 int retCode = mInstaller.clearUserData(packageName);
4171 if (retCode < 0) {
4172 Log.w(TAG, "Couldn't remove cache files for package: "
4173 + packageName);
4174 return false;
4175 }
4176 }
4177 return true;
4178 }
4179
4180 public void deleteApplicationCacheFiles(final String packageName,
4181 final IPackageDataObserver observer) {
4182 mContext.enforceCallingOrSelfPermission(
4183 android.Manifest.permission.DELETE_CACHE_FILES, null);
4184 // Queue up an async operation since the package deletion may take a little while.
4185 mHandler.post(new Runnable() {
4186 public void run() {
4187 mHandler.removeCallbacks(this);
4188 final boolean succeded;
4189 synchronized (mInstallLock) {
4190 succeded = deleteApplicationCacheFilesLI(packageName);
4191 }
4192 if(observer != null) {
4193 try {
4194 observer.onRemoveCompleted(packageName, succeded);
4195 } catch (RemoteException e) {
4196 Log.i(TAG, "Observer no longer exists.");
4197 }
4198 } //end if observer
4199 } //end run
4200 });
4201 }
4202
4203 private boolean deleteApplicationCacheFilesLI(String packageName) {
4204 if (packageName == null) {
4205 Log.w(TAG, "Attempt to delete null packageName.");
4206 return false;
4207 }
4208 PackageParser.Package p;
4209 synchronized (mPackages) {
4210 p = mPackages.get(packageName);
4211 }
4212 if (p == null) {
4213 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4214 return false;
4215 }
4216 final ApplicationInfo applicationInfo = p.applicationInfo;
4217 if (applicationInfo == null) {
4218 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4219 return false;
4220 }
4221 if (mInstaller != null) {
4222 int retCode = mInstaller.deleteCacheFiles(packageName);
4223 if (retCode < 0) {
4224 Log.w(TAG, "Couldn't remove cache files for package: "
4225 + packageName);
4226 return false;
4227 }
4228 }
4229 return true;
4230 }
4231
4232 public void getPackageSizeInfo(final String packageName,
4233 final IPackageStatsObserver observer) {
4234 mContext.enforceCallingOrSelfPermission(
4235 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4236 // Queue up an async operation since the package deletion may take a little while.
4237 mHandler.post(new Runnable() {
4238 public void run() {
4239 mHandler.removeCallbacks(this);
4240 PackageStats lStats = new PackageStats(packageName);
4241 final boolean succeded;
4242 synchronized (mInstallLock) {
4243 succeded = getPackageSizeInfoLI(packageName, lStats);
4244 }
4245 if(observer != null) {
4246 try {
4247 observer.onGetStatsCompleted(lStats, succeded);
4248 } catch (RemoteException e) {
4249 Log.i(TAG, "Observer no longer exists.");
4250 }
4251 } //end if observer
4252 } //end run
4253 });
4254 }
4255
4256 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4257 if (packageName == null) {
4258 Log.w(TAG, "Attempt to get size of null packageName.");
4259 return false;
4260 }
4261 PackageParser.Package p;
4262 boolean dataOnly = false;
4263 synchronized (mPackages) {
4264 p = mPackages.get(packageName);
4265 if(p == null) {
4266 dataOnly = true;
4267 PackageSetting ps = mSettings.mPackages.get(packageName);
4268 if((ps == null) || (ps.pkg == null)) {
4269 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4270 return false;
4271 }
4272 p = ps.pkg;
4273 }
4274 }
4275 String publicSrcDir = null;
4276 if(!dataOnly) {
4277 final ApplicationInfo applicationInfo = p.applicationInfo;
4278 if (applicationInfo == null) {
4279 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4280 return false;
4281 }
4282 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4283 }
4284 if (mInstaller != null) {
4285 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4286 publicSrcDir, pStats);
4287 if (res < 0) {
4288 return false;
4289 } else {
4290 return true;
4291 }
4292 }
4293 return true;
4294 }
4295
4296
4297 public void addPackageToPreferred(String packageName) {
4298 mContext.enforceCallingOrSelfPermission(
4299 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4300
4301 synchronized (mPackages) {
4302 PackageParser.Package p = mPackages.get(packageName);
4303 if (p == null) {
4304 return;
4305 }
4306 PackageSetting ps = (PackageSetting)p.mExtras;
4307 if (ps != null) {
4308 mSettings.mPreferredPackages.remove(ps);
4309 mSettings.mPreferredPackages.add(0, ps);
4310 updatePreferredIndicesLP();
4311 mSettings.writeLP();
4312 }
4313 }
4314 }
4315
4316 public void removePackageFromPreferred(String packageName) {
4317 mContext.enforceCallingOrSelfPermission(
4318 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4319
4320 synchronized (mPackages) {
4321 PackageParser.Package p = mPackages.get(packageName);
4322 if (p == null) {
4323 return;
4324 }
4325 if (p.mPreferredOrder > 0) {
4326 PackageSetting ps = (PackageSetting)p.mExtras;
4327 if (ps != null) {
4328 mSettings.mPreferredPackages.remove(ps);
4329 p.mPreferredOrder = 0;
4330 updatePreferredIndicesLP();
4331 mSettings.writeLP();
4332 }
4333 }
4334 }
4335 }
4336
4337 private void updatePreferredIndicesLP() {
4338 final ArrayList<PackageSetting> pkgs
4339 = mSettings.mPreferredPackages;
4340 final int N = pkgs.size();
4341 for (int i=0; i<N; i++) {
4342 pkgs.get(i).pkg.mPreferredOrder = N - i;
4343 }
4344 }
4345
4346 public List<PackageInfo> getPreferredPackages(int flags) {
4347 synchronized (mPackages) {
4348 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4349 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4350 final int N = pref.size();
4351 for (int i=0; i<N; i++) {
4352 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4353 }
4354 return res;
4355 }
4356 }
4357
4358 public void addPreferredActivity(IntentFilter filter, int match,
4359 ComponentName[] set, ComponentName activity) {
4360 mContext.enforceCallingOrSelfPermission(
4361 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4362
4363 synchronized (mPackages) {
4364 Log.i(TAG, "Adding preferred activity " + activity + ":");
4365 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4366 mSettings.mPreferredActivities.addFilter(
4367 new PreferredActivity(filter, match, set, activity));
4368 mSettings.writeLP();
4369 }
4370 }
4371
4372 public void clearPackagePreferredActivities(String packageName) {
4373 mContext.enforceCallingOrSelfPermission(
4374 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4375
4376 synchronized (mPackages) {
4377 if (clearPackagePreferredActivitiesLP(packageName)) {
4378 mSettings.writeLP();
4379 }
4380 }
4381 }
4382
4383 boolean clearPackagePreferredActivitiesLP(String packageName) {
4384 boolean changed = false;
4385 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4386 while (it.hasNext()) {
4387 PreferredActivity pa = it.next();
4388 if (pa.mActivity.getPackageName().equals(packageName)) {
4389 it.remove();
4390 changed = true;
4391 }
4392 }
4393 return changed;
4394 }
4395
4396 public int getPreferredActivities(List<IntentFilter> outFilters,
4397 List<ComponentName> outActivities, String packageName) {
4398
4399 int num = 0;
4400 synchronized (mPackages) {
4401 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4402 while (it.hasNext()) {
4403 PreferredActivity pa = it.next();
4404 if (packageName == null
4405 || pa.mActivity.getPackageName().equals(packageName)) {
4406 if (outFilters != null) {
4407 outFilters.add(new IntentFilter(pa));
4408 }
4409 if (outActivities != null) {
4410 outActivities.add(pa.mActivity);
4411 }
4412 }
4413 }
4414 }
4415
4416 return num;
4417 }
4418
4419 public void setApplicationEnabledSetting(String appPackageName,
4420 int newState, int flags) {
4421 setEnabledSetting(appPackageName, null, newState, flags);
4422 }
4423
4424 public void setComponentEnabledSetting(ComponentName componentName,
4425 int newState, int flags) {
4426 setEnabledSetting(componentName.getPackageName(),
4427 componentName.getClassName(), newState, flags);
4428 }
4429
4430 private void setEnabledSetting(
4431 final String packageNameStr, String classNameStr, int newState, final int flags) {
4432 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4433 || newState == COMPONENT_ENABLED_STATE_ENABLED
4434 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4435 throw new IllegalArgumentException("Invalid new component state: "
4436 + newState);
4437 }
4438 PackageSetting pkgSetting;
4439 final int uid = Binder.getCallingUid();
4440 final int permission = mContext.checkCallingPermission(
4441 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4442 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4443 int packageUid = -1;
4444 synchronized (mPackages) {
4445 pkgSetting = mSettings.mPackages.get(packageNameStr);
4446 if (pkgSetting == null) {
4447 if (classNameStr == null) {
4448 throw new IllegalArgumentException(
4449 "Unknown package: " + packageNameStr);
4450 }
4451 throw new IllegalArgumentException(
4452 "Unknown component: " + packageNameStr
4453 + "/" + classNameStr);
4454 }
4455 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4456 throw new SecurityException(
4457 "Permission Denial: attempt to change component state from pid="
4458 + Binder.getCallingPid()
4459 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4460 }
4461 packageUid = pkgSetting.userId;
4462 if (classNameStr == null) {
4463 // We're dealing with an application/package level state change
4464 pkgSetting.enabled = newState;
4465 } else {
4466 // We're dealing with a component level state change
4467 switch (newState) {
4468 case COMPONENT_ENABLED_STATE_ENABLED:
4469 pkgSetting.enableComponentLP(classNameStr);
4470 break;
4471 case COMPONENT_ENABLED_STATE_DISABLED:
4472 pkgSetting.disableComponentLP(classNameStr);
4473 break;
4474 case COMPONENT_ENABLED_STATE_DEFAULT:
4475 pkgSetting.restoreComponentLP(classNameStr);
4476 break;
4477 default:
4478 Log.e(TAG, "Invalid new component state: " + newState);
4479 }
4480 }
4481 mSettings.writeLP();
4482 }
4483
4484 long callingId = Binder.clearCallingIdentity();
4485 try {
4486 Bundle extras = new Bundle(2);
4487 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
4488 (flags&PackageManager.DONT_KILL_APP) != 0);
4489 extras.putInt(Intent.EXTRA_UID, packageUid);
4490 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
4491 } finally {
4492 Binder.restoreCallingIdentity(callingId);
4493 }
4494 }
4495
4496 public int getApplicationEnabledSetting(String appPackageName) {
4497 synchronized (mPackages) {
4498 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
4499 if (pkg == null) {
4500 throw new IllegalArgumentException("Unknown package: " + appPackageName);
4501 }
4502 return pkg.enabled;
4503 }
4504 }
4505
4506 public int getComponentEnabledSetting(ComponentName componentName) {
4507 synchronized (mPackages) {
4508 final String packageNameStr = componentName.getPackageName();
4509 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
4510 if (pkg == null) {
4511 throw new IllegalArgumentException("Unknown component: " + componentName);
4512 }
4513 final String classNameStr = componentName.getClassName();
4514 return pkg.currentEnabledStateLP(classNameStr);
4515 }
4516 }
4517
4518 public void enterSafeMode() {
4519 if (!mSystemReady) {
4520 mSafeMode = true;
4521 }
4522 }
4523
4524 public void systemReady() {
4525 mSystemReady = true;
4526 }
4527
4528 public boolean isSafeMode() {
4529 return mSafeMode;
4530 }
4531
4532 public boolean hasSystemUidErrors() {
4533 return mHasSystemUidErrors;
4534 }
4535
4536 static String arrayToString(int[] array) {
4537 StringBuffer buf = new StringBuffer(128);
4538 buf.append('[');
4539 if (array != null) {
4540 for (int i=0; i<array.length; i++) {
4541 if (i > 0) buf.append(", ");
4542 buf.append(array[i]);
4543 }
4544 }
4545 buf.append(']');
4546 return buf.toString();
4547 }
4548
4549 @Override
4550 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4551 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4552 != PackageManager.PERMISSION_GRANTED) {
4553 pw.println("Permission Denial: can't dump ActivityManager from from pid="
4554 + Binder.getCallingPid()
4555 + ", uid=" + Binder.getCallingUid()
4556 + " without permission "
4557 + android.Manifest.permission.DUMP);
4558 return;
4559 }
4560
4561 Printer printer = new PrintWriterPrinter(pw);
4562 synchronized (mPackages) {
4563 pw.println("Activity Resolver Table:");
4564 mActivities.dump(printer, " ");
4565 pw.println(" ");
4566 pw.println("Receiver Resolver Table:");
4567 mReceivers.dump(printer, " ");
4568 pw.println(" ");
4569 pw.println("Service Resolver Table:");
4570 mServices.dump(printer, " ");
4571 pw.println(" ");
4572 pw.println("Preferred Activities:");
4573 mSettings.mPreferredActivities.dump(printer, " ");
4574 pw.println(" ");
4575 pw.println("Preferred Packages:");
4576 {
4577 for (PackageSetting ps : mSettings.mPreferredPackages) {
4578 pw.println(" " + ps.name);
4579 }
4580 }
4581 pw.println(" ");
4582 pw.println("Permissions:");
4583 {
4584 for (BasePermission p : mSettings.mPermissions.values()) {
4585 pw.println(" Permission [" + p.name + "] ("
4586 + Integer.toHexString(System.identityHashCode(p))
4587 + "):");
4588 pw.println(" sourcePackage=" + p.sourcePackage);
4589 pw.println(" uid=" + p.uid
4590 + " gids=" + arrayToString(p.gids)
4591 + " type=" + p.type);
4592 }
4593 }
4594 pw.println(" ");
4595 pw.println("Packages:");
4596 {
4597 for (PackageSetting ps : mSettings.mPackages.values()) {
4598 pw.println(" Package [" + ps.name + "] ("
4599 + Integer.toHexString(System.identityHashCode(ps))
4600 + "):");
4601 pw.println(" userId=" + ps.userId
4602 + " gids=" + arrayToString(ps.gids));
4603 pw.println(" sharedUser=" + ps.sharedUser);
4604 pw.println(" pkg=" + ps.pkg);
4605 pw.println(" codePath=" + ps.codePathString);
4606 pw.println(" resourcePath=" + ps.resourcePathString);
4607 if (ps.pkg != null) {
4608 pw.println(" dataDir=" + ps.pkg.applicationInfo.dataDir);
4609 }
4610 pw.println(" timeStamp=" + ps.getTimeStampStr());
4611 pw.println(" signatures=" + ps.signatures);
4612 pw.println(" permissionsFixed=" + ps.permissionsFixed
4613 + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags)
4614 + " installStatus=" + ps.installStatus
4615 + " enabled=" + ps.enabled);
4616 if (ps.disabledComponents.size() > 0) {
4617 pw.println(" disabledComponents:");
4618 for (String s : ps.disabledComponents) {
4619 pw.println(" " + s);
4620 }
4621 }
4622 if (ps.enabledComponents.size() > 0) {
4623 pw.println(" enabledComponents:");
4624 for (String s : ps.enabledComponents) {
4625 pw.println(" " + s);
4626 }
4627 }
4628 pw.println(" grantedPermissions:");
4629 for (String s : ps.grantedPermissions) {
4630 pw.println(" " + s);
4631 }
4632 pw.println(" loadedPermissions:");
4633 for (String s : ps.loadedPermissions) {
4634 pw.println(" " + s);
4635 }
4636 }
4637 }
4638 pw.println(" ");
4639 pw.println("Shared Users:");
4640 {
4641 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
4642 pw.println(" SharedUser [" + su.name + "] ("
4643 + Integer.toHexString(System.identityHashCode(su))
4644 + "):");
4645 pw.println(" userId=" + su.userId
4646 + " gids=" + arrayToString(su.gids));
4647 pw.println(" grantedPermissions:");
4648 for (String s : su.grantedPermissions) {
4649 pw.println(" " + s);
4650 }
4651 pw.println(" loadedPermissions:");
4652 for (String s : su.loadedPermissions) {
4653 pw.println(" " + s);
4654 }
4655 }
4656 }
4657 pw.println(" ");
4658 pw.println("Settings parse messages:");
4659 pw.println(mSettings.mReadMessages.toString());
4660 }
4661 }
4662
4663 static final class BasePermission {
4664 final static int TYPE_NORMAL = 0;
4665 final static int TYPE_BUILTIN = 1;
4666 final static int TYPE_DYNAMIC = 2;
4667
4668 final String name;
4669 final String sourcePackage;
4670 final int type;
4671 PackageParser.Permission perm;
4672 PermissionInfo pendingInfo;
4673 int uid;
4674 int[] gids;
4675
4676 BasePermission(String _name, String _sourcePackage, int _type) {
4677 name = _name;
4678 sourcePackage = _sourcePackage;
4679 type = _type;
4680 }
4681 }
4682
4683 static class PackageSignatures {
4684 private Signature[] mSignatures;
4685
4686 PackageSignatures(Signature[] sigs) {
4687 assignSignatures(sigs);
4688 }
4689
4690 PackageSignatures() {
4691 }
4692
4693 void writeXml(XmlSerializer serializer, String tagName,
4694 ArrayList<Signature> pastSignatures) throws IOException {
4695 if (mSignatures == null) {
4696 return;
4697 }
4698 serializer.startTag(null, tagName);
4699 serializer.attribute(null, "count",
4700 Integer.toString(mSignatures.length));
4701 for (int i=0; i<mSignatures.length; i++) {
4702 serializer.startTag(null, "cert");
4703 final Signature sig = mSignatures[i];
4704 final int sigHash = sig.hashCode();
4705 final int numPast = pastSignatures.size();
4706 int j;
4707 for (j=0; j<numPast; j++) {
4708 Signature pastSig = pastSignatures.get(j);
4709 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
4710 serializer.attribute(null, "index", Integer.toString(j));
4711 break;
4712 }
4713 }
4714 if (j >= numPast) {
4715 pastSignatures.add(sig);
4716 serializer.attribute(null, "index", Integer.toString(numPast));
4717 serializer.attribute(null, "key", sig.toCharsString());
4718 }
4719 serializer.endTag(null, "cert");
4720 }
4721 serializer.endTag(null, tagName);
4722 }
4723
4724 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
4725 throws IOException, XmlPullParserException {
4726 String countStr = parser.getAttributeValue(null, "count");
4727 if (countStr == null) {
4728 reportSettingsProblem(Log.WARN,
4729 "Error in package manager settings: <signatures> has"
4730 + " no count at " + parser.getPositionDescription());
4731 XmlUtils.skipCurrentTag(parser);
4732 }
4733 final int count = Integer.parseInt(countStr);
4734 mSignatures = new Signature[count];
4735 int pos = 0;
4736
4737 int outerDepth = parser.getDepth();
4738 int type;
4739 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4740 && (type != XmlPullParser.END_TAG
4741 || parser.getDepth() > outerDepth)) {
4742 if (type == XmlPullParser.END_TAG
4743 || type == XmlPullParser.TEXT) {
4744 continue;
4745 }
4746
4747 String tagName = parser.getName();
4748 if (tagName.equals("cert")) {
4749 if (pos < count) {
4750 String index = parser.getAttributeValue(null, "index");
4751 if (index != null) {
4752 try {
4753 int idx = Integer.parseInt(index);
4754 String key = parser.getAttributeValue(null, "key");
4755 if (key == null) {
4756 if (idx >= 0 && idx < pastSignatures.size()) {
4757 Signature sig = pastSignatures.get(idx);
4758 if (sig != null) {
4759 mSignatures[pos] = pastSignatures.get(idx);
4760 pos++;
4761 } else {
4762 reportSettingsProblem(Log.WARN,
4763 "Error in package manager settings: <cert> "
4764 + "index " + index + " is not defined at "
4765 + parser.getPositionDescription());
4766 }
4767 } else {
4768 reportSettingsProblem(Log.WARN,
4769 "Error in package manager settings: <cert> "
4770 + "index " + index + " is out of bounds at "
4771 + parser.getPositionDescription());
4772 }
4773 } else {
4774 while (pastSignatures.size() <= idx) {
4775 pastSignatures.add(null);
4776 }
4777 Signature sig = new Signature(key);
4778 pastSignatures.set(idx, sig);
4779 mSignatures[pos] = sig;
4780 pos++;
4781 }
4782 } catch (NumberFormatException e) {
4783 reportSettingsProblem(Log.WARN,
4784 "Error in package manager settings: <cert> "
4785 + "index " + index + " is not a number at "
4786 + parser.getPositionDescription());
4787 }
4788 } else {
4789 reportSettingsProblem(Log.WARN,
4790 "Error in package manager settings: <cert> has"
4791 + " no index at " + parser.getPositionDescription());
4792 }
4793 } else {
4794 reportSettingsProblem(Log.WARN,
4795 "Error in package manager settings: too "
4796 + "many <cert> tags, expected " + count
4797 + " at " + parser.getPositionDescription());
4798 }
4799 } else {
4800 reportSettingsProblem(Log.WARN,
4801 "Unknown element under <cert>: "
4802 + parser.getName());
4803 }
4804 XmlUtils.skipCurrentTag(parser);
4805 }
4806
4807 if (pos < count) {
4808 // Should never happen -- there is an error in the written
4809 // settings -- but if it does we don't want to generate
4810 // a bad array.
4811 Signature[] newSigs = new Signature[pos];
4812 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
4813 mSignatures = newSigs;
4814 }
4815 }
4816
4817 /**
4818 * If any of the given 'sigs' is contained in the existing signatures,
4819 * then completely replace the current signatures with the ones in
4820 * 'sigs'. This is used for updating an existing package to a newly
4821 * installed version.
4822 */
4823 boolean updateSignatures(Signature[] sigs, boolean update) {
4824 if (mSignatures == null) {
4825 if (update) {
4826 assignSignatures(sigs);
4827 }
4828 return true;
4829 }
4830 if (sigs == null) {
4831 return false;
4832 }
4833
4834 for (int i=0; i<sigs.length; i++) {
4835 Signature sig = sigs[i];
4836 for (int j=0; j<mSignatures.length; j++) {
4837 if (mSignatures[j].equals(sig)) {
4838 if (update) {
4839 assignSignatures(sigs);
4840 }
4841 return true;
4842 }
4843 }
4844 }
4845 return false;
4846 }
4847
4848 /**
4849 * If any of the given 'sigs' is contained in the existing signatures,
4850 * then add in any new signatures found in 'sigs'. This is used for
4851 * including a new package into an existing shared user id.
4852 */
4853 boolean mergeSignatures(Signature[] sigs, boolean update) {
4854 if (mSignatures == null) {
4855 if (update) {
4856 assignSignatures(sigs);
4857 }
4858 return true;
4859 }
4860 if (sigs == null) {
4861 return false;
4862 }
4863
4864 Signature[] added = null;
4865 int addedCount = 0;
4866 boolean haveMatch = false;
4867 for (int i=0; i<sigs.length; i++) {
4868 Signature sig = sigs[i];
4869 boolean found = false;
4870 for (int j=0; j<mSignatures.length; j++) {
4871 if (mSignatures[j].equals(sig)) {
4872 found = true;
4873 haveMatch = true;
4874 break;
4875 }
4876 }
4877
4878 if (!found) {
4879 if (added == null) {
4880 added = new Signature[sigs.length];
4881 }
4882 added[i] = sig;
4883 addedCount++;
4884 }
4885 }
4886
4887 if (!haveMatch) {
4888 // Nothing matched -- reject the new signatures.
4889 return false;
4890 }
4891 if (added == null) {
4892 // Completely matched -- nothing else to do.
4893 return true;
4894 }
4895
4896 // Add additional signatures in.
4897 if (update) {
4898 Signature[] total = new Signature[addedCount+mSignatures.length];
4899 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
4900 int j = mSignatures.length;
4901 for (int i=0; i<added.length; i++) {
4902 if (added[i] != null) {
4903 total[j] = added[i];
4904 j++;
4905 }
4906 }
4907 mSignatures = total;
4908 }
4909 return true;
4910 }
4911
4912 private void assignSignatures(Signature[] sigs) {
4913 if (sigs == null) {
4914 mSignatures = null;
4915 return;
4916 }
4917 mSignatures = new Signature[sigs.length];
4918 for (int i=0; i<sigs.length; i++) {
4919 mSignatures[i] = sigs[i];
4920 }
4921 }
4922
4923 @Override
4924 public String toString() {
4925 StringBuffer buf = new StringBuffer(128);
4926 buf.append("PackageSignatures{");
4927 buf.append(Integer.toHexString(System.identityHashCode(this)));
4928 buf.append(" [");
4929 if (mSignatures != null) {
4930 for (int i=0; i<mSignatures.length; i++) {
4931 if (i > 0) buf.append(", ");
4932 buf.append(Integer.toHexString(
4933 System.identityHashCode(mSignatures[i])));
4934 }
4935 }
4936 buf.append("]}");
4937 return buf.toString();
4938 }
4939 }
4940
4941 static class PreferredActivity extends IntentFilter {
4942 final int mMatch;
4943 final String[] mSetPackages;
4944 final String[] mSetClasses;
4945 final String[] mSetComponents;
4946 final ComponentName mActivity;
4947 final String mShortActivity;
4948 String mParseError;
4949
4950 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
4951 ComponentName activity) {
4952 super(filter);
4953 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
4954 mActivity = activity;
4955 mShortActivity = activity.flattenToShortString();
4956 mParseError = null;
4957 if (set != null) {
4958 final int N = set.length;
4959 String[] myPackages = new String[N];
4960 String[] myClasses = new String[N];
4961 String[] myComponents = new String[N];
4962 for (int i=0; i<N; i++) {
4963 ComponentName cn = set[i];
4964 if (cn == null) {
4965 mSetPackages = null;
4966 mSetClasses = null;
4967 mSetComponents = null;
4968 return;
4969 }
4970 myPackages[i] = cn.getPackageName().intern();
4971 myClasses[i] = cn.getClassName().intern();
4972 myComponents[i] = cn.flattenToShortString().intern();
4973 }
4974 mSetPackages = myPackages;
4975 mSetClasses = myClasses;
4976 mSetComponents = myComponents;
4977 } else {
4978 mSetPackages = null;
4979 mSetClasses = null;
4980 mSetComponents = null;
4981 }
4982 }
4983
4984 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
4985 IOException {
4986 mShortActivity = parser.getAttributeValue(null, "name");
4987 mActivity = ComponentName.unflattenFromString(mShortActivity);
4988 if (mActivity == null) {
4989 mParseError = "Bad activity name " + mShortActivity;
4990 }
4991 String matchStr = parser.getAttributeValue(null, "match");
4992 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
4993 String setCountStr = parser.getAttributeValue(null, "set");
4994 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
4995
4996 String[] myPackages = setCount > 0 ? new String[setCount] : null;
4997 String[] myClasses = setCount > 0 ? new String[setCount] : null;
4998 String[] myComponents = setCount > 0 ? new String[setCount] : null;
4999
5000 int setPos = 0;
5001
5002 int outerDepth = parser.getDepth();
5003 int type;
5004 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5005 && (type != XmlPullParser.END_TAG
5006 || parser.getDepth() > outerDepth)) {
5007 if (type == XmlPullParser.END_TAG
5008 || type == XmlPullParser.TEXT) {
5009 continue;
5010 }
5011
5012 String tagName = parser.getName();
5013 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5014 // + parser.getDepth() + " tag=" + tagName);
5015 if (tagName.equals("set")) {
5016 String name = parser.getAttributeValue(null, "name");
5017 if (name == null) {
5018 if (mParseError == null) {
5019 mParseError = "No name in set tag in preferred activity "
5020 + mShortActivity;
5021 }
5022 } else if (setPos >= setCount) {
5023 if (mParseError == null) {
5024 mParseError = "Too many set tags in preferred activity "
5025 + mShortActivity;
5026 }
5027 } else {
5028 ComponentName cn = ComponentName.unflattenFromString(name);
5029 if (cn == null) {
5030 if (mParseError == null) {
5031 mParseError = "Bad set name " + name + " in preferred activity "
5032 + mShortActivity;
5033 }
5034 } else {
5035 myPackages[setPos] = cn.getPackageName();
5036 myClasses[setPos] = cn.getClassName();
5037 myComponents[setPos] = name;
5038 setPos++;
5039 }
5040 }
5041 XmlUtils.skipCurrentTag(parser);
5042 } else if (tagName.equals("filter")) {
5043 //Log.i(TAG, "Starting to parse filter...");
5044 readFromXml(parser);
5045 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5046 // + parser.getDepth() + " tag=" + parser.getName());
5047 } else {
5048 reportSettingsProblem(Log.WARN,
5049 "Unknown element under <preferred-activities>: "
5050 + parser.getName());
5051 XmlUtils.skipCurrentTag(parser);
5052 }
5053 }
5054
5055 if (setPos != setCount) {
5056 if (mParseError == null) {
5057 mParseError = "Not enough set tags (expected " + setCount
5058 + " but found " + setPos + ") in " + mShortActivity;
5059 }
5060 }
5061
5062 mSetPackages = myPackages;
5063 mSetClasses = myClasses;
5064 mSetComponents = myComponents;
5065 }
5066
5067 public void writeToXml(XmlSerializer serializer) throws IOException {
5068 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5069 serializer.attribute(null, "name", mShortActivity);
5070 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5071 serializer.attribute(null, "set", Integer.toString(NS));
5072 for (int s=0; s<NS; s++) {
5073 serializer.startTag(null, "set");
5074 serializer.attribute(null, "name", mSetComponents[s]);
5075 serializer.endTag(null, "set");
5076 }
5077 serializer.startTag(null, "filter");
5078 super.writeToXml(serializer);
5079 serializer.endTag(null, "filter");
5080 }
5081
5082 boolean sameSet(List<ResolveInfo> query, int priority) {
5083 if (mSetPackages == null) return false;
5084 final int NQ = query.size();
5085 final int NS = mSetPackages.length;
5086 int numMatch = 0;
5087 for (int i=0; i<NQ; i++) {
5088 ResolveInfo ri = query.get(i);
5089 if (ri.priority != priority) continue;
5090 ActivityInfo ai = ri.activityInfo;
5091 boolean good = false;
5092 for (int j=0; j<NS; j++) {
5093 if (mSetPackages[j].equals(ai.packageName)
5094 && mSetClasses[j].equals(ai.name)) {
5095 numMatch++;
5096 good = true;
5097 break;
5098 }
5099 }
5100 if (!good) return false;
5101 }
5102 return numMatch == NS;
5103 }
5104 }
5105
5106 static class GrantedPermissions {
5107 final int pkgFlags;
5108
5109 HashSet<String> grantedPermissions = new HashSet<String>();
5110 int[] gids;
5111
5112 HashSet<String> loadedPermissions = new HashSet<String>();
5113
5114 GrantedPermissions(int pkgFlags) {
5115 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5116 }
5117 }
5118
5119 /**
5120 * Settings base class for pending and resolved classes.
5121 */
5122 static class PackageSettingBase extends GrantedPermissions {
5123 final String name;
5124 final File codePath;
5125 final String codePathString;
5126 final File resourcePath;
5127 final String resourcePathString;
5128 private long timeStamp;
5129 private String timeStampString = "0";
5130
5131 PackageSignatures signatures = new PackageSignatures();
5132
5133 boolean permissionsFixed;
5134
5135 /* Explicitly disabled components */
5136 HashSet<String> disabledComponents = new HashSet<String>(0);
5137 /* Explicitly enabled components */
5138 HashSet<String> enabledComponents = new HashSet<String>(0);
5139 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5140 int installStatus = PKG_INSTALL_COMPLETE;
5141
5142 PackageSettingBase(String name, File codePath, File resourcePath,
5143 int pkgFlags) {
5144 super(pkgFlags);
5145 this.name = name;
5146 this.codePath = codePath;
5147 this.codePathString = codePath.toString();
5148 this.resourcePath = resourcePath;
5149 this.resourcePathString = resourcePath.toString();
5150 }
5151
5152 public void setInstallStatus(int newStatus) {
5153 installStatus = newStatus;
5154 }
5155
5156 public int getInstallStatus() {
5157 return installStatus;
5158 }
5159
5160 public void setTimeStamp(long newStamp) {
5161 if (newStamp != timeStamp) {
5162 timeStamp = newStamp;
5163 timeStampString = Long.toString(newStamp);
5164 }
5165 }
5166
5167 public void setTimeStamp(long newStamp, String newStampStr) {
5168 timeStamp = newStamp;
5169 timeStampString = newStampStr;
5170 }
5171
5172 public long getTimeStamp() {
5173 return timeStamp;
5174 }
5175
5176 public String getTimeStampStr() {
5177 return timeStampString;
5178 }
5179
5180 public void copyFrom(PackageSettingBase base) {
5181 grantedPermissions = base.grantedPermissions;
5182 gids = base.gids;
5183 loadedPermissions = base.loadedPermissions;
5184
5185 timeStamp = base.timeStamp;
5186 timeStampString = base.timeStampString;
5187 signatures = base.signatures;
5188 permissionsFixed = base.permissionsFixed;
5189 disabledComponents = base.disabledComponents;
5190 enabledComponents = base.enabledComponents;
5191 enabled = base.enabled;
5192 installStatus = base.installStatus;
5193 }
5194
5195 void enableComponentLP(String componentClassName) {
5196 disabledComponents.remove(componentClassName);
5197 enabledComponents.add(componentClassName);
5198 }
5199
5200 void disableComponentLP(String componentClassName) {
5201 enabledComponents.remove(componentClassName);
5202 disabledComponents.add(componentClassName);
5203 }
5204
5205 void restoreComponentLP(String componentClassName) {
5206 enabledComponents.remove(componentClassName);
5207 disabledComponents.remove(componentClassName);
5208 }
5209
5210 int currentEnabledStateLP(String componentName) {
5211 if (enabledComponents.contains(componentName)) {
5212 return COMPONENT_ENABLED_STATE_ENABLED;
5213 } else if (disabledComponents.contains(componentName)) {
5214 return COMPONENT_ENABLED_STATE_DISABLED;
5215 } else {
5216 return COMPONENT_ENABLED_STATE_DEFAULT;
5217 }
5218 }
5219 }
5220
5221 /**
5222 * Settings data for a particular package we know about.
5223 */
5224 static final class PackageSetting extends PackageSettingBase {
5225 int userId;
5226 PackageParser.Package pkg;
5227 SharedUserSetting sharedUser;
5228
5229 PackageSetting(String name, File codePath, File resourcePath,
5230 int pkgFlags) {
5231 super(name, codePath, resourcePath, pkgFlags);
5232 }
5233
5234 @Override
5235 public String toString() {
5236 return "PackageSetting{"
5237 + Integer.toHexString(System.identityHashCode(this))
5238 + " " + name + "/" + userId + "}";
5239 }
5240 }
5241
5242 /**
5243 * Settings data for a particular shared user ID we know about.
5244 */
5245 static final class SharedUserSetting extends GrantedPermissions {
5246 final String name;
5247 int userId;
5248 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5249 final PackageSignatures signatures = new PackageSignatures();
5250
5251 SharedUserSetting(String _name, int _pkgFlags) {
5252 super(_pkgFlags);
5253 name = _name;
5254 }
5255
5256 @Override
5257 public String toString() {
5258 return "SharedUserSetting{"
5259 + Integer.toHexString(System.identityHashCode(this))
5260 + " " + name + "/" + userId + "}";
5261 }
5262 }
5263
5264 /**
5265 * Holds information about dynamic settings.
5266 */
5267 private static final class Settings {
5268 private final File mSettingsFilename;
5269 private final File mBackupSettingsFilename;
5270 private final HashMap<String, PackageSetting> mPackages =
5271 new HashMap<String, PackageSetting>();
5272 // The user's preferred packages/applications, in order of preference.
5273 // First is the most preferred.
5274 private final ArrayList<PackageSetting> mPreferredPackages =
5275 new ArrayList<PackageSetting>();
5276 // List of replaced system applications
5277 final HashMap<String, PackageSetting> mDisabledSysPackages =
5278 new HashMap<String, PackageSetting>();
5279
5280 // The user's preferred activities associated with particular intent
5281 // filters.
5282 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5283 new IntentResolver<PreferredActivity, PreferredActivity>() {
5284 @Override
5285 protected void dumpFilter(Printer out, String prefix,
5286 PreferredActivity filter) {
5287 out.println(prefix
5288 + Integer.toHexString(System.identityHashCode(filter))
5289 + " " + filter.mActivity.flattenToShortString()
5290 + " match=0x" + Integer.toHexString(filter.mMatch));
5291 if (filter.mSetComponents != null) {
5292 out.println(prefix + " Selected from:");
5293 for (int i=0; i<filter.mSetComponents.length; i++) {
5294 out.println(prefix + " " + filter.mSetComponents[i]);
5295 }
5296 }
5297 }
5298 };
5299 private final HashMap<String, SharedUserSetting> mSharedUsers =
5300 new HashMap<String, SharedUserSetting>();
5301 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5302 private final SparseArray<Object> mOtherUserIds =
5303 new SparseArray<Object>();
5304
5305 // For reading/writing settings file.
5306 private final ArrayList<Signature> mPastSignatures =
5307 new ArrayList<Signature>();
5308
5309 // Mapping from permission names to info about them.
5310 final HashMap<String, BasePermission> mPermissions =
5311 new HashMap<String, BasePermission>();
5312
5313 // Mapping from permission tree names to info about them.
5314 final HashMap<String, BasePermission> mPermissionTrees =
5315 new HashMap<String, BasePermission>();
5316
5317 private final ArrayList<String> mPendingPreferredPackages
5318 = new ArrayList<String>();
5319
5320 private final StringBuilder mReadMessages = new StringBuilder();
5321
5322 private static final class PendingPackage extends PackageSettingBase {
5323 final int sharedId;
5324
5325 PendingPackage(String name, File codePath, File resourcePath,
5326 int sharedId, int pkgFlags) {
5327 super(name, codePath, resourcePath, pkgFlags);
5328 this.sharedId = sharedId;
5329 }
5330 }
5331 private final ArrayList<PendingPackage> mPendingPackages
5332 = new ArrayList<PendingPackage>();
5333
5334 Settings() {
5335 File dataDir = Environment.getDataDirectory();
5336 File systemDir = new File(dataDir, "system");
5337 systemDir.mkdirs();
5338 FileUtils.setPermissions(systemDir.toString(),
5339 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5340 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5341 -1, -1);
5342 mSettingsFilename = new File(systemDir, "packages.xml");
5343 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5344 }
5345
5346 PackageSetting getPackageLP(PackageParser.Package pkg,
5347 SharedUserSetting sharedUser, File codePath, File resourcePath,
5348 int pkgFlags, boolean create, boolean add) {
5349 final String name = pkg.packageName;
5350 PackageSetting p = getPackageLP(name, sharedUser, codePath,
5351 resourcePath, pkgFlags, create, add);
5352
5353 if (p != null) {
5354 p.pkg = pkg;
5355 }
5356 return p;
5357 }
5358
5359 PackageSetting peekPackageLP(String name, String codePath) {
5360 PackageSetting p = mPackages.get(name);
5361 if (p != null && p.codePath.getPath().equals(codePath)) {
5362 return p;
5363 }
5364 return null;
5365 }
5366
5367 void setInstallStatus(String pkgName, int status) {
5368 PackageSetting p = mPackages.get(pkgName);
5369 if(p != null) {
5370 if(p.getInstallStatus() != status) {
5371 p.setInstallStatus(status);
5372 }
5373 }
5374 }
5375
5376 int getInstallStatus(String pkgName) {
5377 PackageSetting p = mPackages.get(pkgName);
5378 if(p != null) {
5379 return p.getInstallStatus();
5380 }
5381 return -1;
5382 }
5383
5384 SharedUserSetting getSharedUserLP(String name,
5385 int pkgFlags, boolean create) {
5386 SharedUserSetting s = mSharedUsers.get(name);
5387 if (s == null) {
5388 if (!create) {
5389 return null;
5390 }
5391 s = new SharedUserSetting(name, pkgFlags);
5392 if (MULTIPLE_APPLICATION_UIDS) {
5393 s.userId = newUserIdLP(s);
5394 } else {
5395 s.userId = FIRST_APPLICATION_UID;
5396 }
5397 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
5398 // < 0 means we couldn't assign a userid; fall out and return
5399 // s, which is currently null
5400 if (s.userId >= 0) {
5401 mSharedUsers.put(name, s);
5402 }
5403 }
5404
5405 return s;
5406 }
5407
5408 int disableSystemPackageLP(String name) {
5409 PackageSetting p = mPackages.get(name);
5410 if(p == null) {
5411 Log.w(TAG, "Package:"+name+" is not an installed package");
5412 return -1;
5413 }
5414 PackageSetting dp = mDisabledSysPackages.get(name);
5415 // always make sure the system package code and resource paths dont change
5416 if(dp == null) {
5417 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5418 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5419 }
5420 mDisabledSysPackages.put(name, p);
5421 }
5422 return removePackageLP(name);
5423 }
5424
5425 PackageSetting enableSystemPackageLP(String name) {
5426 PackageSetting p = mDisabledSysPackages.get(name);
5427 if(p == null) {
5428 Log.w(TAG, "Package:"+name+" is not disabled");
5429 return null;
5430 }
5431 // Reset flag in ApplicationInfo object
5432 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5433 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5434 }
5435 PackageSetting ret = addPackageLP(name, p.codePath,
5436 p.resourcePath, p.userId, p.pkgFlags);
5437 mDisabledSysPackages.remove(name);
5438 return ret;
5439 }
5440
5441 PackageSetting addPackageLP(String name, File codePath,
5442 File resourcePath, int uid, int pkgFlags) {
5443 PackageSetting p = mPackages.get(name);
5444 if (p != null) {
5445 if (p.userId == uid) {
5446 return p;
5447 }
5448 reportSettingsProblem(Log.ERROR,
5449 "Adding duplicate package, keeping first: " + name);
5450 return null;
5451 }
5452 p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
5453 p.userId = uid;
5454 if (addUserIdLP(uid, p, name)) {
5455 mPackages.put(name, p);
5456 return p;
5457 }
5458 return null;
5459 }
5460
5461 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
5462 SharedUserSetting s = mSharedUsers.get(name);
5463 if (s != null) {
5464 if (s.userId == uid) {
5465 return s;
5466 }
5467 reportSettingsProblem(Log.ERROR,
5468 "Adding duplicate shared user, keeping first: " + name);
5469 return null;
5470 }
5471 s = new SharedUserSetting(name, pkgFlags);
5472 s.userId = uid;
5473 if (addUserIdLP(uid, s, name)) {
5474 mSharedUsers.put(name, s);
5475 return s;
5476 }
5477 return null;
5478 }
5479
5480 private PackageSetting getPackageLP(String name,
5481 SharedUserSetting sharedUser, File codePath, File resourcePath,
5482 int pkgFlags, boolean create, boolean add) {
5483 PackageSetting p = mPackages.get(name);
5484 if (p != null) {
5485 if (!p.codePath.equals(codePath)) {
5486 // Check to see if its a disabled system app
5487 PackageSetting ps = mDisabledSysPackages.get(name);
5488 if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
5489 // Could be a replaced system package
5490 // Note that if the user replaced a system app, the user has to physically
5491 // delete the new one in order to revert to the system app. So even
5492 // if the user updated the system app via an update, the user still
5493 // has to delete the one installed in the data partition in order to pick up the
5494 // new system package.
5495 return p;
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07005496 } else if ((p.pkg != null) && (p.pkg.applicationInfo != null) &&
5497 ((p.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
5498 // Check for non-system apps
5499 reportSettingsProblem(Log.WARN,
5500 "Package " + name + " codePath changed from " + p.codePath
5501 + " to " + codePath + "; Retaining data and using new code");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 } else {
5503 reportSettingsProblem(Log.WARN,
5504 "Package " + name + " codePath changed from " + p.codePath
5505 + " to " + codePath + "; replacing with new");
5506 p = null;
5507 }
5508 } else if (p.sharedUser != sharedUser) {
5509 reportSettingsProblem(Log.WARN,
5510 "Package " + name + " shared user changed from "
5511 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
5512 + " to "
5513 + (sharedUser != null ? sharedUser.name : "<nothing>")
5514 + "; replacing with new");
5515 p = null;
5516 }
5517 }
5518 if (p == null) {
5519 // Create a new PackageSettings entry. this can end up here because
5520 // of code path mismatch or user id mismatch of an updated system partition
5521 if (!create) {
5522 return null;
5523 }
5524 p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
5525 p.setTimeStamp(codePath.lastModified());
5526 if (sharedUser != null) {
5527 p.userId = sharedUser.userId;
5528 } else if (MULTIPLE_APPLICATION_UIDS) {
5529 p.userId = newUserIdLP(p);
5530 } else {
5531 p.userId = FIRST_APPLICATION_UID;
5532 }
5533 if (p.userId < 0) {
5534 reportSettingsProblem(Log.WARN,
5535 "Package " + name + " could not be assigned a valid uid");
5536 return null;
5537 }
5538 if (add) {
5539 // Finish adding new package by adding it and updating shared
5540 // user preferences
5541 insertPackageSettingLP(p, name, sharedUser);
5542 }
5543 }
5544 return p;
5545 }
5546
5547 // Utility method that adds a PackageSetting to mPackages and
5548 // completes updating the shared user attributes
5549 private void insertPackageSettingLP(PackageSetting p, String name,
5550 SharedUserSetting sharedUser) {
5551 mPackages.put(name, p);
5552 if (sharedUser != null) {
5553 if (p.sharedUser != null && p.sharedUser != sharedUser) {
5554 reportSettingsProblem(Log.ERROR,
5555 "Package " + p.name + " was user "
5556 + p.sharedUser + " but is now " + sharedUser
5557 + "; I am not changing its files so it will probably fail!");
5558 p.sharedUser.packages.remove(p);
5559 } else if (p.userId != sharedUser.userId) {
5560 reportSettingsProblem(Log.ERROR,
5561 "Package " + p.name + " was user id " + p.userId
5562 + " but is now user " + sharedUser
5563 + " with id " + sharedUser.userId
5564 + "; I am not changing its files so it will probably fail!");
5565 }
5566
5567 sharedUser.packages.add(p);
5568 p.sharedUser = sharedUser;
5569 p.userId = sharedUser.userId;
5570 }
5571 }
5572
5573 private void updateSharedUserPerms (PackageSetting deletedPs) {
5574 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
5575 Log.i(TAG, "Trying to update info for null package. Just ignoring");
5576 return;
5577 }
5578 // No sharedUserId
5579 if (deletedPs.sharedUser == null) {
5580 return;
5581 }
5582 SharedUserSetting sus = deletedPs.sharedUser;
5583 // Update permissions
5584 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
5585 boolean used = false;
5586 if (!sus.grantedPermissions.contains (eachPerm)) {
5587 continue;
5588 }
5589 for (PackageSetting pkg:sus.packages) {
5590 if (pkg.grantedPermissions.contains (eachPerm)) {
5591 used = true;
5592 break;
5593 }
5594 }
5595 if (!used) {
5596 // can safely delete this permission from list
5597 sus.grantedPermissions.remove(eachPerm);
5598 sus.loadedPermissions.remove(eachPerm);
5599 }
5600 }
5601 // Update gids
5602 int newGids[] = null;
5603 for (PackageSetting pkg:sus.packages) {
5604 newGids = appendInts(newGids, pkg.gids);
5605 }
5606 sus.gids = newGids;
5607 }
5608
5609 private int removePackageLP(String name) {
5610 PackageSetting p = mPackages.get(name);
5611 if (p != null) {
5612 mPackages.remove(name);
5613 if (p.sharedUser != null) {
5614 p.sharedUser.packages.remove(p);
5615 if (p.sharedUser.packages.size() == 0) {
5616 mSharedUsers.remove(p.sharedUser.name);
5617 removeUserIdLP(p.sharedUser.userId);
5618 return p.sharedUser.userId;
5619 }
5620 } else {
5621 removeUserIdLP(p.userId);
5622 return p.userId;
5623 }
5624 }
5625 return -1;
5626 }
5627
5628 private boolean addUserIdLP(int uid, Object obj, Object name) {
5629 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
5630 return false;
5631 }
5632
5633 if (uid >= FIRST_APPLICATION_UID) {
5634 int N = mUserIds.size();
5635 final int index = uid - FIRST_APPLICATION_UID;
5636 while (index >= N) {
5637 mUserIds.add(null);
5638 N++;
5639 }
5640 if (mUserIds.get(index) != null) {
5641 reportSettingsProblem(Log.ERROR,
5642 "Adding duplicate shared id: " + uid
5643 + " name=" + name);
5644 return false;
5645 }
5646 mUserIds.set(index, obj);
5647 } else {
5648 if (mOtherUserIds.get(uid) != null) {
5649 reportSettingsProblem(Log.ERROR,
5650 "Adding duplicate shared id: " + uid
5651 + " name=" + name);
5652 return false;
5653 }
5654 mOtherUserIds.put(uid, obj);
5655 }
5656 return true;
5657 }
5658
5659 public Object getUserIdLP(int uid) {
5660 if (uid >= FIRST_APPLICATION_UID) {
5661 int N = mUserIds.size();
5662 final int index = uid - FIRST_APPLICATION_UID;
5663 return index < N ? mUserIds.get(index) : null;
5664 } else {
5665 return mOtherUserIds.get(uid);
5666 }
5667 }
5668
5669 private void removeUserIdLP(int uid) {
5670 if (uid >= FIRST_APPLICATION_UID) {
5671 int N = mUserIds.size();
5672 final int index = uid - FIRST_APPLICATION_UID;
5673 if (index < N) mUserIds.set(index, null);
5674 } else {
5675 mOtherUserIds.remove(uid);
5676 }
5677 }
5678
5679 void writeLP() {
5680 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
5681
5682 // Keep the old settings around until we know the new ones have
5683 // been successfully written.
5684 if (mSettingsFilename.exists()) {
5685 if (mBackupSettingsFilename.exists()) {
5686 mBackupSettingsFilename.delete();
5687 }
5688 mSettingsFilename.renameTo(mBackupSettingsFilename);
5689 }
5690
5691 mPastSignatures.clear();
5692
5693 try {
5694 FileOutputStream str = new FileOutputStream(mSettingsFilename);
5695
5696 //XmlSerializer serializer = XmlUtils.serializerInstance();
5697 XmlSerializer serializer = new FastXmlSerializer();
5698 serializer.setOutput(str, "utf-8");
5699 serializer.startDocument(null, true);
5700 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
5701
5702 serializer.startTag(null, "packages");
5703
5704 serializer.startTag(null, "permission-trees");
5705 for (BasePermission bp : mPermissionTrees.values()) {
5706 writePermission(serializer, bp);
5707 }
5708 serializer.endTag(null, "permission-trees");
5709
5710 serializer.startTag(null, "permissions");
5711 for (BasePermission bp : mPermissions.values()) {
5712 writePermission(serializer, bp);
5713 }
5714 serializer.endTag(null, "permissions");
5715
5716 for (PackageSetting pkg : mPackages.values()) {
5717 writePackage(serializer, pkg);
5718 }
5719
5720 for (PackageSetting pkg : mDisabledSysPackages.values()) {
5721 writeDisabledSysPackage(serializer, pkg);
5722 }
5723
5724 serializer.startTag(null, "preferred-packages");
5725 int N = mPreferredPackages.size();
5726 for (int i=0; i<N; i++) {
5727 PackageSetting pkg = mPreferredPackages.get(i);
5728 serializer.startTag(null, "item");
5729 serializer.attribute(null, "name", pkg.name);
5730 serializer.endTag(null, "item");
5731 }
5732 serializer.endTag(null, "preferred-packages");
5733
5734 serializer.startTag(null, "preferred-activities");
5735 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
5736 serializer.startTag(null, "item");
5737 pa.writeToXml(serializer);
5738 serializer.endTag(null, "item");
5739 }
5740 serializer.endTag(null, "preferred-activities");
5741
5742 for (SharedUserSetting usr : mSharedUsers.values()) {
5743 serializer.startTag(null, "shared-user");
5744 serializer.attribute(null, "name", usr.name);
5745 serializer.attribute(null, "userId",
5746 Integer.toString(usr.userId));
5747 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
5748 serializer.startTag(null, "perms");
5749 for (String name : usr.grantedPermissions) {
5750 serializer.startTag(null, "item");
5751 serializer.attribute(null, "name", name);
5752 serializer.endTag(null, "item");
5753 }
5754 serializer.endTag(null, "perms");
5755 serializer.endTag(null, "shared-user");
5756 }
5757
5758 serializer.endTag(null, "packages");
5759
5760 serializer.endDocument();
5761
5762 str.flush();
5763 str.close();
5764
5765 // New settings successfully written, old ones are no longer
5766 // needed.
5767 mBackupSettingsFilename.delete();
5768 FileUtils.setPermissions(mSettingsFilename.toString(),
5769 FileUtils.S_IRUSR|FileUtils.S_IWUSR
5770 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
5771 |FileUtils.S_IROTH,
5772 -1, -1);
5773
5774 } catch(XmlPullParserException e) {
5775 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5776
5777 } catch(java.io.IOException e) {
5778 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5779
5780 }
5781
5782 //Debug.stopMethodTracing();
5783 }
5784
5785 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
5786 throws java.io.IOException {
5787 serializer.startTag(null, "updated-package");
5788 serializer.attribute(null, "name", pkg.name);
5789 serializer.attribute(null, "codePath", pkg.codePathString);
5790 serializer.attribute(null, "ts", pkg.getTimeStampStr());
5791 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5792 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5793 }
5794 if (pkg.sharedUser == null) {
5795 serializer.attribute(null, "userId",
5796 Integer.toString(pkg.userId));
5797 } else {
5798 serializer.attribute(null, "sharedUserId",
5799 Integer.toString(pkg.userId));
5800 }
5801 serializer.startTag(null, "perms");
5802 if (pkg.sharedUser == null) {
5803 // If this is a shared user, the permissions will
5804 // be written there. We still need to write an
5805 // empty permissions list so permissionsFixed will
5806 // be set.
5807 for (final String name : pkg.grantedPermissions) {
5808 BasePermission bp = mPermissions.get(name);
5809 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
5810 // We only need to write signature or system permissions but this wont
5811 // match the semantics of grantedPermissions. So write all permissions.
5812 serializer.startTag(null, "item");
5813 serializer.attribute(null, "name", name);
5814 serializer.endTag(null, "item");
5815 }
5816 }
5817 }
5818 serializer.endTag(null, "perms");
5819 serializer.endTag(null, "updated-package");
5820 }
5821
5822 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
5823 throws java.io.IOException {
5824 serializer.startTag(null, "package");
5825 serializer.attribute(null, "name", pkg.name);
5826 serializer.attribute(null, "codePath", pkg.codePathString);
5827 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5828 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5829 }
5830 serializer.attribute(null, "system",
5831 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
5832 ? "true" : "false");
5833 serializer.attribute(null, "ts", pkg.getTimeStampStr());
5834 if (pkg.sharedUser == null) {
5835 serializer.attribute(null, "userId",
5836 Integer.toString(pkg.userId));
5837 } else {
5838 serializer.attribute(null, "sharedUserId",
5839 Integer.toString(pkg.userId));
5840 }
5841 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
5842 serializer.attribute(null, "enabled",
5843 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
5844 ? "true" : "false");
5845 }
5846 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
5847 serializer.attribute(null, "installStatus", "false");
5848 }
5849 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
5850 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5851 serializer.startTag(null, "perms");
5852 if (pkg.sharedUser == null) {
5853 // If this is a shared user, the permissions will
5854 // be written there. We still need to write an
5855 // empty permissions list so permissionsFixed will
5856 // be set.
5857 for (final String name : pkg.grantedPermissions) {
5858 serializer.startTag(null, "item");
5859 serializer.attribute(null, "name", name);
5860 serializer.endTag(null, "item");
5861 }
5862 }
5863 serializer.endTag(null, "perms");
5864 }
5865 if (pkg.disabledComponents.size() > 0) {
5866 serializer.startTag(null, "disabled-components");
5867 for (final String name : pkg.disabledComponents) {
5868 serializer.startTag(null, "item");
5869 serializer.attribute(null, "name", name);
5870 serializer.endTag(null, "item");
5871 }
5872 serializer.endTag(null, "disabled-components");
5873 }
5874 if (pkg.enabledComponents.size() > 0) {
5875 serializer.startTag(null, "enabled-components");
5876 for (final String name : pkg.enabledComponents) {
5877 serializer.startTag(null, "item");
5878 serializer.attribute(null, "name", name);
5879 serializer.endTag(null, "item");
5880 }
5881 serializer.endTag(null, "enabled-components");
5882 }
5883 serializer.endTag(null, "package");
5884 }
5885
5886 void writePermission(XmlSerializer serializer, BasePermission bp)
5887 throws XmlPullParserException, java.io.IOException {
5888 if (bp.type != BasePermission.TYPE_BUILTIN
5889 && bp.sourcePackage != null) {
5890 serializer.startTag(null, "item");
5891 serializer.attribute(null, "name", bp.name);
5892 serializer.attribute(null, "package", bp.sourcePackage);
5893 if (DEBUG_SETTINGS) Log.v(TAG,
5894 "Writing perm: name=" + bp.name + " type=" + bp.type);
5895 if (bp.type == BasePermission.TYPE_DYNAMIC) {
5896 PermissionInfo pi = bp.perm != null ? bp.perm.info
5897 : bp.pendingInfo;
5898 if (pi != null) {
5899 serializer.attribute(null, "type", "dynamic");
5900 if (pi.icon != 0) {
5901 serializer.attribute(null, "icon",
5902 Integer.toString(pi.icon));
5903 }
5904 if (pi.nonLocalizedLabel != null) {
5905 serializer.attribute(null, "label",
5906 pi.nonLocalizedLabel.toString());
5907 }
5908 if (pi.protectionLevel !=
5909 PermissionInfo.PROTECTION_NORMAL) {
5910 serializer.attribute(null, "protection",
5911 Integer.toString(pi.protectionLevel));
5912 }
5913 }
5914 }
5915 serializer.endTag(null, "item");
5916 }
5917 }
5918
5919 String getReadMessagesLP() {
5920 return mReadMessages.toString();
5921 }
5922
5923 ArrayList<String> getListOfIncompleteInstallPackages() {
5924 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
5925 Iterator<String> its = kList.iterator();
5926 ArrayList<String> ret = new ArrayList<String>();
5927 while(its.hasNext()) {
5928 String key = its.next();
5929 PackageSetting ps = mPackages.get(key);
5930 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
5931 ret.add(key);
5932 }
5933 }
5934 return ret;
5935 }
5936
5937 boolean readLP() {
5938 FileInputStream str = null;
5939 if (mBackupSettingsFilename.exists()) {
5940 try {
5941 str = new FileInputStream(mBackupSettingsFilename);
5942 mReadMessages.append("Reading from backup settings file\n");
5943 Log.i(TAG, "Reading from backup settings file!");
5944 } catch (java.io.IOException e) {
5945 // We'll try for the normal settings file.
5946 }
5947 }
5948
5949 mPastSignatures.clear();
5950
5951 try {
5952 if (str == null) {
5953 if (!mSettingsFilename.exists()) {
5954 mReadMessages.append("No settings file found\n");
5955 Log.i(TAG, "No current settings file!");
5956 return false;
5957 }
5958 str = new FileInputStream(mSettingsFilename);
5959 }
5960 XmlPullParser parser = Xml.newPullParser();
5961 parser.setInput(str, null);
5962
5963 int type;
5964 while ((type=parser.next()) != XmlPullParser.START_TAG
5965 && type != XmlPullParser.END_DOCUMENT) {
5966 ;
5967 }
5968
5969 if (type != XmlPullParser.START_TAG) {
5970 mReadMessages.append("No start tag found in settings file\n");
5971 Log.e(TAG, "No start tag found in package manager settings");
5972 return false;
5973 }
5974
5975 int outerDepth = parser.getDepth();
5976 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5977 && (type != XmlPullParser.END_TAG
5978 || parser.getDepth() > outerDepth)) {
5979 if (type == XmlPullParser.END_TAG
5980 || type == XmlPullParser.TEXT) {
5981 continue;
5982 }
5983
5984 String tagName = parser.getName();
5985 if (tagName.equals("package")) {
5986 readPackageLP(parser);
5987 } else if (tagName.equals("permissions")) {
5988 readPermissionsLP(mPermissions, parser);
5989 } else if (tagName.equals("permission-trees")) {
5990 readPermissionsLP(mPermissionTrees, parser);
5991 } else if (tagName.equals("shared-user")) {
5992 readSharedUserLP(parser);
5993 } else if (tagName.equals("preferred-packages")) {
5994 readPreferredPackagesLP(parser);
5995 } else if (tagName.equals("preferred-activities")) {
5996 readPreferredActivitiesLP(parser);
5997 } else if(tagName.equals("updated-package")) {
5998 readDisabledSysPackageLP(parser);
5999 } else {
6000 Log.w(TAG, "Unknown element under <packages>: "
6001 + parser.getName());
6002 XmlUtils.skipCurrentTag(parser);
6003 }
6004 }
6005
6006 str.close();
6007
6008 } catch(XmlPullParserException e) {
6009 mReadMessages.append("Error reading: " + e.toString());
6010 Log.e(TAG, "Error reading package manager settings", e);
6011
6012 } catch(java.io.IOException e) {
6013 mReadMessages.append("Error reading: " + e.toString());
6014 Log.e(TAG, "Error reading package manager settings", e);
6015
6016 }
6017
6018 int N = mPendingPackages.size();
6019 for (int i=0; i<N; i++) {
6020 final PendingPackage pp = mPendingPackages.get(i);
6021 Object idObj = getUserIdLP(pp.sharedId);
6022 if (idObj != null && idObj instanceof SharedUserSetting) {
6023 PackageSetting p = getPackageLP(pp.name,
6024 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
6025 pp.pkgFlags, true, true);
6026 if (p == null) {
6027 Log.w(TAG, "Unable to create application package for "
6028 + pp.name);
6029 continue;
6030 }
6031 p.copyFrom(pp);
6032 } else if (idObj != null) {
6033 String msg = "Bad package setting: package " + pp.name
6034 + " has shared uid " + pp.sharedId
6035 + " that is not a shared uid\n";
6036 mReadMessages.append(msg);
6037 Log.e(TAG, msg);
6038 } else {
6039 String msg = "Bad package setting: package " + pp.name
6040 + " has shared uid " + pp.sharedId
6041 + " that is not defined\n";
6042 mReadMessages.append(msg);
6043 Log.e(TAG, msg);
6044 }
6045 }
6046 mPendingPackages.clear();
6047
6048 N = mPendingPreferredPackages.size();
6049 mPreferredPackages.clear();
6050 for (int i=0; i<N; i++) {
6051 final String name = mPendingPreferredPackages.get(i);
6052 final PackageSetting p = mPackages.get(name);
6053 if (p != null) {
6054 mPreferredPackages.add(p);
6055 } else {
6056 Log.w(TAG, "Unknown preferred package: " + name);
6057 }
6058 }
6059 mPendingPreferredPackages.clear();
6060
6061 mReadMessages.append("Read completed successfully: "
6062 + mPackages.size() + " packages, "
6063 + mSharedUsers.size() + " shared uids\n");
6064
6065 return true;
6066 }
6067
6068 private int readInt(XmlPullParser parser, String ns, String name,
6069 int defValue) {
6070 String v = parser.getAttributeValue(ns, name);
6071 try {
6072 if (v == null) {
6073 return defValue;
6074 }
6075 return Integer.parseInt(v);
6076 } catch (NumberFormatException e) {
6077 reportSettingsProblem(Log.WARN,
6078 "Error in package manager settings: attribute " +
6079 name + " has bad integer value " + v + " at "
6080 + parser.getPositionDescription());
6081 }
6082 return defValue;
6083 }
6084
6085 private void readPermissionsLP(HashMap<String, BasePermission> out,
6086 XmlPullParser parser)
6087 throws IOException, XmlPullParserException {
6088 int outerDepth = parser.getDepth();
6089 int type;
6090 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6091 && (type != XmlPullParser.END_TAG
6092 || parser.getDepth() > outerDepth)) {
6093 if (type == XmlPullParser.END_TAG
6094 || type == XmlPullParser.TEXT) {
6095 continue;
6096 }
6097
6098 String tagName = parser.getName();
6099 if (tagName.equals("item")) {
6100 String name = parser.getAttributeValue(null, "name");
6101 String sourcePackage = parser.getAttributeValue(null, "package");
6102 String ptype = parser.getAttributeValue(null, "type");
6103 if (name != null && sourcePackage != null) {
6104 boolean dynamic = "dynamic".equals(ptype);
6105 BasePermission bp = new BasePermission(name, sourcePackage,
6106 dynamic
6107 ? BasePermission.TYPE_DYNAMIC
6108 : BasePermission.TYPE_NORMAL);
6109 if (dynamic) {
6110 PermissionInfo pi = new PermissionInfo();
6111 pi.packageName = sourcePackage.intern();
6112 pi.name = name.intern();
6113 pi.icon = readInt(parser, null, "icon", 0);
6114 pi.nonLocalizedLabel = parser.getAttributeValue(
6115 null, "label");
6116 pi.protectionLevel = readInt(parser, null, "protection",
6117 PermissionInfo.PROTECTION_NORMAL);
6118 bp.pendingInfo = pi;
6119 }
6120 out.put(bp.name, bp);
6121 } else {
6122 reportSettingsProblem(Log.WARN,
6123 "Error in package manager settings: permissions has"
6124 + " no name at " + parser.getPositionDescription());
6125 }
6126 } else {
6127 reportSettingsProblem(Log.WARN,
6128 "Unknown element reading permissions: "
6129 + parser.getName() + " at "
6130 + parser.getPositionDescription());
6131 }
6132 XmlUtils.skipCurrentTag(parser);
6133 }
6134 }
6135
6136 private void readDisabledSysPackageLP(XmlPullParser parser)
6137 throws XmlPullParserException, IOException {
6138 String name = parser.getAttributeValue(null, "name");
6139 String codePathStr = parser.getAttributeValue(null, "codePath");
6140 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6141 if(resourcePathStr == null) {
6142 resourcePathStr = codePathStr;
6143 }
6144
6145 int pkgFlags = 0;
6146 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6147 PackageSetting ps = new PackageSetting(name,
6148 new File(codePathStr),
6149 new File(resourcePathStr), pkgFlags);
6150 String timeStampStr = parser.getAttributeValue(null, "ts");
6151 if (timeStampStr != null) {
6152 try {
6153 long timeStamp = Long.parseLong(timeStampStr);
6154 ps.setTimeStamp(timeStamp, timeStampStr);
6155 } catch (NumberFormatException e) {
6156 }
6157 }
6158 String idStr = parser.getAttributeValue(null, "userId");
6159 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6160 if(ps.userId <= 0) {
6161 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6162 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6163 }
6164 int outerDepth = parser.getDepth();
6165 int type;
6166 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6167 && (type != XmlPullParser.END_TAG
6168 || parser.getDepth() > outerDepth)) {
6169 if (type == XmlPullParser.END_TAG
6170 || type == XmlPullParser.TEXT) {
6171 continue;
6172 }
6173
6174 String tagName = parser.getName();
6175 if (tagName.equals("perms")) {
6176 readGrantedPermissionsLP(parser,
6177 ps.grantedPermissions);
6178 } else {
6179 reportSettingsProblem(Log.WARN,
6180 "Unknown element under <updated-package>: "
6181 + parser.getName());
6182 XmlUtils.skipCurrentTag(parser);
6183 }
6184 }
6185 mDisabledSysPackages.put(name, ps);
6186 }
6187
6188 private void readPackageLP(XmlPullParser parser)
6189 throws XmlPullParserException, IOException {
6190 String name = null;
6191 String idStr = null;
6192 String sharedIdStr = null;
6193 String codePathStr = null;
6194 String resourcePathStr = null;
6195 String systemStr = null;
6196 int pkgFlags = 0;
6197 String timeStampStr;
6198 long timeStamp = 0;
6199 PackageSettingBase packageSetting = null;
6200 try {
6201 name = parser.getAttributeValue(null, "name");
6202 idStr = parser.getAttributeValue(null, "userId");
6203 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6204 codePathStr = parser.getAttributeValue(null, "codePath");
6205 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6206 systemStr = parser.getAttributeValue(null, "system");
6207 if (systemStr != null) {
6208 if ("true".equals(systemStr)) {
6209 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6210 }
6211 } else {
6212 // Old settings that don't specify system... just treat
6213 // them as system, good enough.
6214 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6215 }
6216 timeStampStr = parser.getAttributeValue(null, "ts");
6217 if (timeStampStr != null) {
6218 try {
6219 timeStamp = Long.parseLong(timeStampStr);
6220 } catch (NumberFormatException e) {
6221 }
6222 }
6223 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6224 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6225 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6226 if (resourcePathStr == null) {
6227 resourcePathStr = codePathStr;
6228 }
6229 if (name == null) {
6230 reportSettingsProblem(Log.WARN,
6231 "Error in package manager settings: <package> has no name at "
6232 + parser.getPositionDescription());
6233 } else if (codePathStr == null) {
6234 reportSettingsProblem(Log.WARN,
6235 "Error in package manager settings: <package> has no codePath at "
6236 + parser.getPositionDescription());
6237 } else if (userId > 0) {
6238 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
6239 new File(resourcePathStr), userId, pkgFlags);
6240 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6241 + ": userId=" + userId + " pkg=" + packageSetting);
6242 if (packageSetting == null) {
6243 reportSettingsProblem(Log.ERROR,
6244 "Failure adding uid " + userId
6245 + " while parsing settings at "
6246 + parser.getPositionDescription());
6247 } else {
6248 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6249 }
6250 } else if (sharedIdStr != null) {
6251 userId = sharedIdStr != null
6252 ? Integer.parseInt(sharedIdStr) : 0;
6253 if (userId > 0) {
6254 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
6255 new File(resourcePathStr), userId, pkgFlags);
6256 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6257 mPendingPackages.add((PendingPackage) packageSetting);
6258 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6259 + ": sharedUserId=" + userId + " pkg="
6260 + packageSetting);
6261 } else {
6262 reportSettingsProblem(Log.WARN,
6263 "Error in package manager settings: package "
6264 + name + " has bad sharedId " + sharedIdStr
6265 + " at " + parser.getPositionDescription());
6266 }
6267 } else {
6268 reportSettingsProblem(Log.WARN,
6269 "Error in package manager settings: package "
6270 + name + " has bad userId " + idStr + " at "
6271 + parser.getPositionDescription());
6272 }
6273 } catch (NumberFormatException e) {
6274 reportSettingsProblem(Log.WARN,
6275 "Error in package manager settings: package "
6276 + name + " has bad userId " + idStr + " at "
6277 + parser.getPositionDescription());
6278 }
6279 if (packageSetting != null) {
6280 final String enabledStr = parser.getAttributeValue(null, "enabled");
6281 if (enabledStr != null) {
6282 if (enabledStr.equalsIgnoreCase("true")) {
6283 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
6284 } else if (enabledStr.equalsIgnoreCase("false")) {
6285 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
6286 } else if (enabledStr.equalsIgnoreCase("default")) {
6287 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6288 } else {
6289 reportSettingsProblem(Log.WARN,
6290 "Error in package manager settings: package "
6291 + name + " has bad enabled value: " + idStr
6292 + " at " + parser.getPositionDescription());
6293 }
6294 } else {
6295 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6296 }
6297 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
6298 if (installStatusStr != null) {
6299 if (installStatusStr.equalsIgnoreCase("false")) {
6300 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
6301 } else {
6302 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
6303 }
6304 }
6305
6306 int outerDepth = parser.getDepth();
6307 int type;
6308 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6309 && (type != XmlPullParser.END_TAG
6310 || parser.getDepth() > outerDepth)) {
6311 if (type == XmlPullParser.END_TAG
6312 || type == XmlPullParser.TEXT) {
6313 continue;
6314 }
6315
6316 String tagName = parser.getName();
6317 if (tagName.equals("disabled-components")) {
6318 readDisabledComponentsLP(packageSetting, parser);
6319 } else if (tagName.equals("enabled-components")) {
6320 readEnabledComponentsLP(packageSetting, parser);
6321 } else if (tagName.equals("sigs")) {
6322 packageSetting.signatures.readXml(parser, mPastSignatures);
6323 } else if (tagName.equals("perms")) {
6324 readGrantedPermissionsLP(parser,
6325 packageSetting.loadedPermissions);
6326 packageSetting.permissionsFixed = true;
6327 } else {
6328 reportSettingsProblem(Log.WARN,
6329 "Unknown element under <package>: "
6330 + parser.getName());
6331 XmlUtils.skipCurrentTag(parser);
6332 }
6333 }
6334 } else {
6335 XmlUtils.skipCurrentTag(parser);
6336 }
6337 }
6338
6339 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
6340 XmlPullParser parser)
6341 throws IOException, XmlPullParserException {
6342 int outerDepth = parser.getDepth();
6343 int type;
6344 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6345 && (type != XmlPullParser.END_TAG
6346 || parser.getDepth() > outerDepth)) {
6347 if (type == XmlPullParser.END_TAG
6348 || type == XmlPullParser.TEXT) {
6349 continue;
6350 }
6351
6352 String tagName = parser.getName();
6353 if (tagName.equals("item")) {
6354 String name = parser.getAttributeValue(null, "name");
6355 if (name != null) {
6356 packageSetting.disabledComponents.add(name.intern());
6357 } else {
6358 reportSettingsProblem(Log.WARN,
6359 "Error in package manager settings: <disabled-components> has"
6360 + " no name at " + parser.getPositionDescription());
6361 }
6362 } else {
6363 reportSettingsProblem(Log.WARN,
6364 "Unknown element under <disabled-components>: "
6365 + parser.getName());
6366 }
6367 XmlUtils.skipCurrentTag(parser);
6368 }
6369 }
6370
6371 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
6372 XmlPullParser parser)
6373 throws IOException, XmlPullParserException {
6374 int outerDepth = parser.getDepth();
6375 int type;
6376 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6377 && (type != XmlPullParser.END_TAG
6378 || parser.getDepth() > outerDepth)) {
6379 if (type == XmlPullParser.END_TAG
6380 || type == XmlPullParser.TEXT) {
6381 continue;
6382 }
6383
6384 String tagName = parser.getName();
6385 if (tagName.equals("item")) {
6386 String name = parser.getAttributeValue(null, "name");
6387 if (name != null) {
6388 packageSetting.enabledComponents.add(name.intern());
6389 } else {
6390 reportSettingsProblem(Log.WARN,
6391 "Error in package manager settings: <enabled-components> has"
6392 + " no name at " + parser.getPositionDescription());
6393 }
6394 } else {
6395 reportSettingsProblem(Log.WARN,
6396 "Unknown element under <enabled-components>: "
6397 + parser.getName());
6398 }
6399 XmlUtils.skipCurrentTag(parser);
6400 }
6401 }
6402
6403 private void readSharedUserLP(XmlPullParser parser)
6404 throws XmlPullParserException, IOException {
6405 String name = null;
6406 String idStr = null;
6407 int pkgFlags = 0;
6408 SharedUserSetting su = null;
6409 try {
6410 name = parser.getAttributeValue(null, "name");
6411 idStr = parser.getAttributeValue(null, "userId");
6412 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6413 if ("true".equals(parser.getAttributeValue(null, "system"))) {
6414 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6415 }
6416 if (name == null) {
6417 reportSettingsProblem(Log.WARN,
6418 "Error in package manager settings: <shared-user> has no name at "
6419 + parser.getPositionDescription());
6420 } else if (userId == 0) {
6421 reportSettingsProblem(Log.WARN,
6422 "Error in package manager settings: shared-user "
6423 + name + " has bad userId " + idStr + " at "
6424 + parser.getPositionDescription());
6425 } else {
6426 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
6427 reportSettingsProblem(Log.ERROR,
6428 "Occurred while parsing settings at "
6429 + parser.getPositionDescription());
6430 }
6431 }
6432 } catch (NumberFormatException e) {
6433 reportSettingsProblem(Log.WARN,
6434 "Error in package manager settings: package "
6435 + name + " has bad userId " + idStr + " at "
6436 + parser.getPositionDescription());
6437 };
6438
6439 if (su != null) {
6440 int outerDepth = parser.getDepth();
6441 int type;
6442 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6443 && (type != XmlPullParser.END_TAG
6444 || parser.getDepth() > outerDepth)) {
6445 if (type == XmlPullParser.END_TAG
6446 || type == XmlPullParser.TEXT) {
6447 continue;
6448 }
6449
6450 String tagName = parser.getName();
6451 if (tagName.equals("sigs")) {
6452 su.signatures.readXml(parser, mPastSignatures);
6453 } else if (tagName.equals("perms")) {
6454 readGrantedPermissionsLP(parser, su.loadedPermissions);
6455 } else {
6456 reportSettingsProblem(Log.WARN,
6457 "Unknown element under <shared-user>: "
6458 + parser.getName());
6459 XmlUtils.skipCurrentTag(parser);
6460 }
6461 }
6462
6463 } else {
6464 XmlUtils.skipCurrentTag(parser);
6465 }
6466 }
6467
6468 private void readGrantedPermissionsLP(XmlPullParser parser,
6469 HashSet<String> outPerms) throws IOException, XmlPullParserException {
6470 int outerDepth = parser.getDepth();
6471 int type;
6472 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6473 && (type != XmlPullParser.END_TAG
6474 || parser.getDepth() > outerDepth)) {
6475 if (type == XmlPullParser.END_TAG
6476 || type == XmlPullParser.TEXT) {
6477 continue;
6478 }
6479
6480 String tagName = parser.getName();
6481 if (tagName.equals("item")) {
6482 String name = parser.getAttributeValue(null, "name");
6483 if (name != null) {
6484 outPerms.add(name.intern());
6485 } else {
6486 reportSettingsProblem(Log.WARN,
6487 "Error in package manager settings: <perms> has"
6488 + " no name at " + parser.getPositionDescription());
6489 }
6490 } else {
6491 reportSettingsProblem(Log.WARN,
6492 "Unknown element under <perms>: "
6493 + parser.getName());
6494 }
6495 XmlUtils.skipCurrentTag(parser);
6496 }
6497 }
6498
6499 private void readPreferredPackagesLP(XmlPullParser parser)
6500 throws XmlPullParserException, IOException {
6501 int outerDepth = parser.getDepth();
6502 int type;
6503 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6504 && (type != XmlPullParser.END_TAG
6505 || parser.getDepth() > outerDepth)) {
6506 if (type == XmlPullParser.END_TAG
6507 || type == XmlPullParser.TEXT) {
6508 continue;
6509 }
6510
6511 String tagName = parser.getName();
6512 if (tagName.equals("item")) {
6513 String name = parser.getAttributeValue(null, "name");
6514 if (name != null) {
6515 mPendingPreferredPackages.add(name);
6516 } else {
6517 reportSettingsProblem(Log.WARN,
6518 "Error in package manager settings: <preferred-package> has no name at "
6519 + parser.getPositionDescription());
6520 }
6521 } else {
6522 reportSettingsProblem(Log.WARN,
6523 "Unknown element under <preferred-packages>: "
6524 + parser.getName());
6525 }
6526 XmlUtils.skipCurrentTag(parser);
6527 }
6528 }
6529
6530 private void readPreferredActivitiesLP(XmlPullParser parser)
6531 throws XmlPullParserException, IOException {
6532 int outerDepth = parser.getDepth();
6533 int type;
6534 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6535 && (type != XmlPullParser.END_TAG
6536 || parser.getDepth() > outerDepth)) {
6537 if (type == XmlPullParser.END_TAG
6538 || type == XmlPullParser.TEXT) {
6539 continue;
6540 }
6541
6542 String tagName = parser.getName();
6543 if (tagName.equals("item")) {
6544 PreferredActivity pa = new PreferredActivity(parser);
6545 if (pa.mParseError == null) {
6546 mPreferredActivities.addFilter(pa);
6547 } else {
6548 reportSettingsProblem(Log.WARN,
6549 "Error in package manager settings: <preferred-activity> "
6550 + pa.mParseError + " at "
6551 + parser.getPositionDescription());
6552 }
6553 } else {
6554 reportSettingsProblem(Log.WARN,
6555 "Unknown element under <preferred-activities>: "
6556 + parser.getName());
6557 XmlUtils.skipCurrentTag(parser);
6558 }
6559 }
6560 }
6561
6562 // Returns -1 if we could not find an available UserId to assign
6563 private int newUserIdLP(Object obj) {
6564 // Let's be stupidly inefficient for now...
6565 final int N = mUserIds.size();
6566 for (int i=0; i<N; i++) {
6567 if (mUserIds.get(i) == null) {
6568 mUserIds.set(i, obj);
6569 return FIRST_APPLICATION_UID + i;
6570 }
6571 }
6572
6573 // None left?
6574 if (N >= MAX_APPLICATION_UIDS) {
6575 return -1;
6576 }
6577
6578 mUserIds.add(obj);
6579 return FIRST_APPLICATION_UID + N;
6580 }
6581
6582 public PackageSetting getDisabledSystemPkg(String name) {
6583 synchronized(mPackages) {
6584 PackageSetting ps = mDisabledSysPackages.get(name);
6585 return ps;
6586 }
6587 }
6588
6589 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
6590 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
6591 if (Config.LOGV) {
6592 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
6593 + " componentName = " + componentInfo.name);
6594 Log.v(TAG, "enabledComponents: "
6595 + Arrays.toString(packageSettings.enabledComponents.toArray()));
6596 Log.v(TAG, "disabledComponents: "
6597 + Arrays.toString(packageSettings.disabledComponents.toArray()));
6598 }
6599 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
6600 || ((componentInfo.enabled
6601 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
6602 || (componentInfo.applicationInfo.enabled
6603 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
6604 && !packageSettings.disabledComponents.contains(componentInfo.name))
6605 || packageSettings.enabledComponents.contains(componentInfo.name));
6606 }
6607 }
6608}