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