blob: fec3608a3eab4f382ccac18d13bbc8f6e12008d9 [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;
60import android.content.pm.PackageParser.Package;
61import android.net.Uri;
62import android.os.Binder;
63import android.os.Bundle;
64import android.os.HandlerThread;
65import android.os.Parcel;
66import android.os.RemoteException;
67import android.os.Environment;
68import android.os.FileObserver;
69import android.os.FileUtils;
70import android.os.Handler;
71import android.os.ParcelFileDescriptor;
72import android.os.Process;
73import android.os.ServiceManager;
74import android.os.SystemClock;
75import android.os.SystemProperties;
76import android.util.*;
77import android.view.Display;
78import android.view.WindowManager;
79
80import java.io.File;
81import java.io.FileDescriptor;
82import java.io.FileInputStream;
83import java.io.FileNotFoundException;
84import java.io.FileOutputStream;
85import java.io.FileReader;
86import java.io.FilenameFilter;
87import java.io.IOException;
88import java.io.InputStream;
89import java.io.PrintWriter;
90import java.util.ArrayList;
91import java.util.Arrays;
92import java.util.Collections;
93import java.util.Comparator;
94import java.util.Enumeration;
95import java.util.HashMap;
96import java.util.HashSet;
97import java.util.Iterator;
98import java.util.List;
99import java.util.Map;
100import java.util.Set;
101import java.util.zip.ZipEntry;
102import java.util.zip.ZipFile;
103import java.util.zip.ZipOutputStream;
104
105class PackageManagerService extends IPackageManager.Stub {
106 private static final String TAG = "PackageManager";
107 private static final boolean DEBUG_SETTINGS = false;
108 private static final boolean DEBUG_PREFERRED = false;
109
110 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
111 private static final int RADIO_UID = Process.PHONE_UID;
112 private static final int FIRST_APPLICATION_UID =
113 Process.FIRST_APPLICATION_UID;
114 private static final int MAX_APPLICATION_UIDS = 1000;
115
116 private static final boolean SHOW_INFO = false;
117
118 private static final boolean GET_CERTIFICATES = true;
119
120 private static final int REMOVE_EVENTS =
121 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
122 private static final int ADD_EVENTS =
123 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
124
125 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
126
127 static final int SCAN_MONITOR = 1<<0;
128 static final int SCAN_NO_DEX = 1<<1;
129 static final int SCAN_FORCE_DEX = 1<<2;
130 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
131 static final int SCAN_FORWARD_LOCKED = 1<<4;
132
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 }
1966 }
1967
1968 if (removeExisting) {
1969 if (mInstaller != null) {
1970 int ret = mInstaller.remove(pkgName);
1971 if (ret != 0) {
1972 String msg = "System package " + pkg.packageName
1973 + " could not have data directory erased after signature change.";
1974 reportSettingsProblem(Log.WARN, msg);
1975 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
1976 return null;
1977 }
1978 }
1979 Log.w(TAG, "System package " + pkg.packageName
1980 + " signature changed: existing data removed.");
1981 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1982 }
1983
1984 long scanFileTime = scanFile.lastModified();
1985 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
1986 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
1987 pkg.applicationInfo.processName = fixProcessName(
1988 pkg.applicationInfo.packageName,
1989 pkg.applicationInfo.processName,
1990 pkg.applicationInfo.uid);
1991 pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
1992
1993 File dataPath;
1994 if (mPlatformPackage == pkg) {
1995 // The system package is special.
1996 dataPath = new File (Environment.getDataDirectory(), "system");
1997 pkg.applicationInfo.dataDir = dataPath.getPath();
1998 } else {
1999 // This is a normal package, need to make its data directory.
2000 dataPath = new File(mAppDataDir, pkgName);
2001 if (dataPath.exists()) {
2002 mOutPermissions[1] = 0;
2003 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2004 if (mOutPermissions[1] == pkg.applicationInfo.uid
2005 || !Process.supportsProcesses()) {
2006 pkg.applicationInfo.dataDir = dataPath.getPath();
2007 } else {
2008 boolean recovered = false;
2009 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2010 // If this is a system app, we can at least delete its
2011 // current data so the application will still work.
2012 if (mInstaller != null) {
2013 int ret = mInstaller.remove(pkgName);
2014 if(ret >= 0) {
2015 // Old data gone!
2016 String msg = "System package " + pkg.packageName
2017 + " has changed from uid: "
2018 + mOutPermissions[1] + " to "
2019 + pkg.applicationInfo.uid + "; old data erased";
2020 reportSettingsProblem(Log.WARN, msg);
2021 recovered = true;
2022
2023 // And now re-install the app.
2024 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2025 pkg.applicationInfo.uid);
2026 if (ret == -1) {
2027 // Ack should not happen!
2028 msg = "System package " + pkg.packageName
2029 + " could not have data directory re-created after delete.";
2030 reportSettingsProblem(Log.WARN, msg);
2031 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2032 return null;
2033 }
2034 }
2035 }
2036 if (!recovered) {
2037 mHasSystemUidErrors = true;
2038 }
2039 }
2040 if (!recovered) {
2041 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2042 + pkg.applicationInfo.uid + "/fs_"
2043 + mOutPermissions[1];
2044 String msg = "Package " + pkg.packageName
2045 + " has mismatched uid: "
2046 + mOutPermissions[1] + " on disk, "
2047 + pkg.applicationInfo.uid + " in settings";
2048 synchronized (mPackages) {
2049 if (!mReportedUidError) {
2050 mReportedUidError = true;
2051 msg = msg + "; read messages:\n"
2052 + mSettings.getReadMessagesLP();
2053 }
2054 reportSettingsProblem(Log.ERROR, msg);
2055 }
2056 }
2057 }
2058 pkg.applicationInfo.dataDir = dataPath.getPath();
2059 } else {
2060 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2061 Log.v(TAG, "Want this data dir: " + dataPath);
2062 //invoke installer to do the actual installation
2063 if (mInstaller != null) {
2064 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2065 pkg.applicationInfo.uid);
2066 if(ret < 0) {
2067 // Error from installer
2068 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2069 return null;
2070 }
2071 } else {
2072 dataPath.mkdirs();
2073 if (dataPath.exists()) {
2074 FileUtils.setPermissions(
2075 dataPath.toString(),
2076 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2077 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2078 }
2079 }
2080 if (dataPath.exists()) {
2081 pkg.applicationInfo.dataDir = dataPath.getPath();
2082 } else {
2083 Log.w(TAG, "Unable to create data directory: " + dataPath);
2084 pkg.applicationInfo.dataDir = null;
2085 }
2086 }
2087 }
2088
2089 // Perform shared library installation and dex validation and
2090 // optimization, if this is not a system app.
2091 if (mInstaller != null) {
2092 String path = scanFile.getPath();
2093 if (scanFileNewer) {
2094 Log.i(TAG, path + " changed; unpacking");
2095 try {
2096 cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2097 } catch (IOException e) {
2098 Log.e(TAG, "Failure extracting shared libs", e);
2099 if(mInstaller != null) {
2100 mInstaller.remove(pkgName);
2101 } else {
2102 dataPath.delete();
2103 }
2104 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2105 return null;
2106 }
2107 }
2108
2109 if ((scanMode&SCAN_NO_DEX) == 0
2110 && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
2111 int ret = 0;
2112 try {
2113 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2114 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2115 (scanMode&SCAN_FORWARD_LOCKED) == 0);
2116 }
2117 } catch (FileNotFoundException e) {
2118 Log.w(TAG, "Apk not found for dexopt: " + path);
2119 ret = -1;
2120 } catch (IOException e) {
2121 Log.w(TAG, "Exception reading apk: " + path, e);
2122 ret = -1;
2123 }
2124 if (ret < 0) {
2125 //error from installer
2126 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2127 return null;
2128 }
2129 }
2130 }
2131
2132 if (mFactoryTest && pkg.requestedPermissions.contains(
2133 android.Manifest.permission.FACTORY_TEST)) {
2134 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2135 }
2136
2137 if ((scanMode&SCAN_MONITOR) != 0) {
2138 pkg.mPath = destCodeFile.getAbsolutePath();
2139 mAppDirs.put(pkg.mPath, pkg);
2140 }
2141
2142 synchronized (mPackages) {
2143 // We don't expect installation to fail beyond this point
2144 // Add the new setting to mSettings
2145 mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
2146 // Add the new setting to mPackages
2147 mPackages.put(pkg.applicationInfo.packageName, pkg);
2148 int N = pkg.providers.size();
2149 StringBuilder r = null;
2150 int i;
2151 for (i=0; i<N; i++) {
2152 PackageParser.Provider p = pkg.providers.get(i);
2153 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2154 p.info.processName, pkg.applicationInfo.uid);
2155 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2156 p.info.name), p);
2157 p.syncable = p.info.isSyncable;
2158 String names[] = p.info.authority.split(";");
2159 p.info.authority = null;
2160 for (int j = 0; j < names.length; j++) {
2161 if (j == 1 && p.syncable) {
2162 // We only want the first authority for a provider to possibly be
2163 // syncable, so if we already added this provider using a different
2164 // authority clear the syncable flag. We copy the provider before
2165 // changing it because the mProviders object contains a reference
2166 // to a provider that we don't want to change.
2167 // Only do this for the second authority since the resulting provider
2168 // object can be the same for all future authorities for this provider.
2169 p = new PackageParser.Provider(p);
2170 p.syncable = false;
2171 }
2172 if (!mProviders.containsKey(names[j])) {
2173 mProviders.put(names[j], p);
2174 if (p.info.authority == null) {
2175 p.info.authority = names[j];
2176 } else {
2177 p.info.authority = p.info.authority + ";" + names[j];
2178 }
2179 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2180 Log.d(TAG, "Registered content provider: " + names[j] +
2181 ", className = " + p.info.name +
2182 ", isSyncable = " + p.info.isSyncable);
2183 } else {
2184 Log.w(TAG, "Skipping provider name " + names[j] +
2185 " (in package " + pkg.applicationInfo.packageName +
2186 "): name already used");
2187 }
2188 }
2189 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2190 if (r == null) {
2191 r = new StringBuilder(256);
2192 } else {
2193 r.append(' ');
2194 }
2195 r.append(p.info.name);
2196 }
2197 }
2198 if (r != null) {
2199 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2200 }
2201
2202 N = pkg.services.size();
2203 r = null;
2204 for (i=0; i<N; i++) {
2205 PackageParser.Service s = pkg.services.get(i);
2206 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2207 s.info.processName, pkg.applicationInfo.uid);
2208 mServices.addService(s);
2209 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2210 if (r == null) {
2211 r = new StringBuilder(256);
2212 } else {
2213 r.append(' ');
2214 }
2215 r.append(s.info.name);
2216 }
2217 }
2218 if (r != null) {
2219 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2220 }
2221
2222 N = pkg.receivers.size();
2223 r = null;
2224 for (i=0; i<N; i++) {
2225 PackageParser.Activity a = pkg.receivers.get(i);
2226 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2227 a.info.processName, pkg.applicationInfo.uid);
2228 mReceivers.addActivity(a, "receiver");
2229 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2230 if (r == null) {
2231 r = new StringBuilder(256);
2232 } else {
2233 r.append(' ');
2234 }
2235 r.append(a.info.name);
2236 }
2237 }
2238 if (r != null) {
2239 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2240 }
2241
2242 N = pkg.activities.size();
2243 r = null;
2244 for (i=0; i<N; i++) {
2245 PackageParser.Activity a = pkg.activities.get(i);
2246 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2247 a.info.processName, pkg.applicationInfo.uid);
2248 mActivities.addActivity(a, "activity");
2249 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2250 if (r == null) {
2251 r = new StringBuilder(256);
2252 } else {
2253 r.append(' ');
2254 }
2255 r.append(a.info.name);
2256 }
2257 }
2258 if (r != null) {
2259 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2260 }
2261
2262 N = pkg.permissionGroups.size();
2263 r = null;
2264 for (i=0; i<N; i++) {
2265 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2266 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2267 if (cur == null) {
2268 mPermissionGroups.put(pg.info.name, pg);
2269 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2270 if (r == null) {
2271 r = new StringBuilder(256);
2272 } else {
2273 r.append(' ');
2274 }
2275 r.append(pg.info.name);
2276 }
2277 } else {
2278 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2279 + pg.info.packageName + " ignored: original from "
2280 + cur.info.packageName);
2281 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2282 if (r == null) {
2283 r = new StringBuilder(256);
2284 } else {
2285 r.append(' ');
2286 }
2287 r.append("DUP:");
2288 r.append(pg.info.name);
2289 }
2290 }
2291 }
2292 if (r != null) {
2293 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2294 }
2295
2296 N = pkg.permissions.size();
2297 r = null;
2298 for (i=0; i<N; i++) {
2299 PackageParser.Permission p = pkg.permissions.get(i);
2300 HashMap<String, BasePermission> permissionMap =
2301 p.tree ? mSettings.mPermissionTrees
2302 : mSettings.mPermissions;
2303 p.group = mPermissionGroups.get(p.info.group);
2304 if (p.info.group == null || p.group != null) {
2305 BasePermission bp = permissionMap.get(p.info.name);
2306 if (bp == null) {
2307 bp = new BasePermission(p.info.name, p.info.packageName,
2308 BasePermission.TYPE_NORMAL);
2309 permissionMap.put(p.info.name, bp);
2310 }
2311 if (bp.perm == null) {
2312 if (bp.sourcePackage == null
2313 || bp.sourcePackage.equals(p.info.packageName)) {
2314 BasePermission tree = findPermissionTreeLP(p.info.name);
2315 if (tree == null
2316 || tree.sourcePackage.equals(p.info.packageName)) {
2317 bp.perm = p;
2318 bp.uid = pkg.applicationInfo.uid;
2319 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2320 if (r == null) {
2321 r = new StringBuilder(256);
2322 } else {
2323 r.append(' ');
2324 }
2325 r.append(p.info.name);
2326 }
2327 } else {
2328 Log.w(TAG, "Permission " + p.info.name + " from package "
2329 + p.info.packageName + " ignored: base tree "
2330 + tree.name + " is from package "
2331 + tree.sourcePackage);
2332 }
2333 } else {
2334 Log.w(TAG, "Permission " + p.info.name + " from package "
2335 + p.info.packageName + " ignored: original from "
2336 + bp.sourcePackage);
2337 }
2338 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2339 if (r == null) {
2340 r = new StringBuilder(256);
2341 } else {
2342 r.append(' ');
2343 }
2344 r.append("DUP:");
2345 r.append(p.info.name);
2346 }
2347 } else {
2348 Log.w(TAG, "Permission " + p.info.name + " from package "
2349 + p.info.packageName + " ignored: no group "
2350 + p.group);
2351 }
2352 }
2353 if (r != null) {
2354 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2355 }
2356
2357 N = pkg.instrumentation.size();
2358 r = null;
2359 for (i=0; i<N; i++) {
2360 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2361 a.info.packageName = pkg.applicationInfo.packageName;
2362 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2363 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2364 a.info.dataDir = pkg.applicationInfo.dataDir;
2365 mInstrumentation.put(a.component, a);
2366 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2367 if (r == null) {
2368 r = new StringBuilder(256);
2369 } else {
2370 r.append(' ');
2371 }
2372 r.append(a.info.name);
2373 }
2374 }
2375 if (r != null) {
2376 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2377 }
2378
2379 pkgSetting.setTimeStamp(scanFileTime);
2380 }
2381
2382 return pkg;
2383 }
2384
2385 private void cachePackageSharedLibsLI(PackageParser.Package pkg,
2386 File dataPath, File scanFile) throws IOException {
2387 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2388 final String sharedLibraryABI = "armeabi";
2389 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2390 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2391 final String sharedLibrarySuffix = ".so";
2392 boolean createdSharedLib = false;
2393 try {
2394 ZipFile zipFile = new ZipFile(scanFile);
2395 Enumeration<ZipEntry> entries =
2396 (Enumeration<ZipEntry>) zipFile.entries();
2397
2398 while (entries.hasMoreElements()) {
2399 ZipEntry entry = entries.nextElement();
2400 if (entry.isDirectory()) {
2401 continue;
2402 }
2403 String entryName = entry.getName();
2404 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2405 && entryName.endsWith(sharedLibrarySuffix))) {
2406 continue;
2407 }
2408 String libFileName = entryName.substring(
2409 apkLibraryDirectory.length());
2410 if (libFileName.contains("/")
2411 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2412 continue;
2413 }
2414 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2415 File.separator + libFileName;
2416 File sharedLibraryFile = new File(sharedLibraryFilePath);
2417 if (! sharedLibraryFile.exists() ||
2418 sharedLibraryFile.length() != entry.getSize() ||
2419 sharedLibraryFile.lastModified() != entry.getTime()) {
2420 if (Config.LOGD) {
2421 Log.d(TAG, "Caching shared lib " + entry.getName());
2422 }
2423 if (mInstaller == null) {
2424 sharedLibraryDir.mkdir();
2425 createdSharedLib = true;
2426 }
2427 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2428 sharedLibraryFile);
2429 }
2430 }
2431 } catch (IOException e) {
2432 Log.e(TAG, "Failed to cache package shared libs", e);
2433 if(createdSharedLib) {
2434 sharedLibraryDir.delete();
2435 }
2436 throw e;
2437 }
2438 }
2439
2440 private void cacheSharedLibLI(PackageParser.Package pkg,
2441 ZipFile zipFile, ZipEntry entry,
2442 File sharedLibraryDir,
2443 File sharedLibraryFile) throws IOException {
2444 InputStream inputStream = zipFile.getInputStream(entry);
2445 try {
2446 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2447 String tempFilePath = tempFile.getPath();
2448 // XXX package manager can't change owner, so the lib files for
2449 // now need to be left as world readable and owned by the system.
2450 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2451 ! tempFile.setLastModified(entry.getTime()) ||
2452 FileUtils.setPermissions(tempFilePath,
2453 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2454 |FileUtils.S_IROTH, -1, -1) != 0 ||
2455 ! tempFile.renameTo(sharedLibraryFile)) {
2456 // Failed to properly write file.
2457 tempFile.delete();
2458 throw new IOException("Couldn't create cached shared lib "
2459 + sharedLibraryFile + " in " + sharedLibraryDir);
2460 }
2461 } finally {
2462 inputStream.close();
2463 }
2464 }
2465
2466 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2467 if (chatty && Config.LOGD) Log.d(
2468 TAG, "Removing package " + pkg.applicationInfo.packageName );
2469
2470 synchronized (mPackages) {
2471 if (pkg.mPreferredOrder > 0) {
2472 mSettings.mPreferredPackages.remove(pkg);
2473 pkg.mPreferredOrder = 0;
2474 updatePreferredIndicesLP();
2475 }
2476
2477 clearPackagePreferredActivitiesLP(pkg.packageName);
2478
2479 mPackages.remove(pkg.applicationInfo.packageName);
2480 if (pkg.mPath != null) {
2481 mAppDirs.remove(pkg.mPath);
2482 }
2483
2484 PackageSetting ps = (PackageSetting)pkg.mExtras;
2485 if (ps != null && ps.sharedUser != null) {
2486 // XXX don't do this until the data is removed.
2487 if (false) {
2488 ps.sharedUser.packages.remove(ps);
2489 if (ps.sharedUser.packages.size() == 0) {
2490 // Remove.
2491 }
2492 }
2493 }
2494
2495 int N = pkg.providers.size();
2496 StringBuilder r = null;
2497 int i;
2498 for (i=0; i<N; i++) {
2499 PackageParser.Provider p = pkg.providers.get(i);
2500 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2501 p.info.name));
2502 if (p.info.authority == null) {
2503
2504 /* The is another ContentProvider with this authority when
2505 * this app was installed so this authority is null,
2506 * Ignore it as we don't have to unregister the provider.
2507 */
2508 continue;
2509 }
2510 String names[] = p.info.authority.split(";");
2511 for (int j = 0; j < names.length; j++) {
2512 if (mProviders.get(names[j]) == p) {
2513 mProviders.remove(names[j]);
2514 if (chatty && Config.LOGD) Log.d(
2515 TAG, "Unregistered content provider: " + names[j] +
2516 ", className = " + p.info.name +
2517 ", isSyncable = " + p.info.isSyncable);
2518 }
2519 }
2520 if (chatty) {
2521 if (r == null) {
2522 r = new StringBuilder(256);
2523 } else {
2524 r.append(' ');
2525 }
2526 r.append(p.info.name);
2527 }
2528 }
2529 if (r != null) {
2530 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2531 }
2532
2533 N = pkg.services.size();
2534 r = null;
2535 for (i=0; i<N; i++) {
2536 PackageParser.Service s = pkg.services.get(i);
2537 mServices.removeService(s);
2538 if (chatty) {
2539 if (r == null) {
2540 r = new StringBuilder(256);
2541 } else {
2542 r.append(' ');
2543 }
2544 r.append(s.info.name);
2545 }
2546 }
2547 if (r != null) {
2548 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2549 }
2550
2551 N = pkg.receivers.size();
2552 r = null;
2553 for (i=0; i<N; i++) {
2554 PackageParser.Activity a = pkg.receivers.get(i);
2555 mReceivers.removeActivity(a, "receiver");
2556 if (chatty) {
2557 if (r == null) {
2558 r = new StringBuilder(256);
2559 } else {
2560 r.append(' ');
2561 }
2562 r.append(a.info.name);
2563 }
2564 }
2565 if (r != null) {
2566 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2567 }
2568
2569 N = pkg.activities.size();
2570 r = null;
2571 for (i=0; i<N; i++) {
2572 PackageParser.Activity a = pkg.activities.get(i);
2573 mActivities.removeActivity(a, "activity");
2574 if (chatty) {
2575 if (r == null) {
2576 r = new StringBuilder(256);
2577 } else {
2578 r.append(' ');
2579 }
2580 r.append(a.info.name);
2581 }
2582 }
2583 if (r != null) {
2584 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2585 }
2586
2587 N = pkg.permissions.size();
2588 r = null;
2589 for (i=0; i<N; i++) {
2590 PackageParser.Permission p = pkg.permissions.get(i);
2591 boolean tree = false;
2592 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2593 if (bp == null) {
2594 tree = true;
2595 bp = mSettings.mPermissionTrees.get(p.info.name);
2596 }
2597 if (bp != null && bp.perm == p) {
2598 if (bp.type != BasePermission.TYPE_BUILTIN) {
2599 if (tree) {
2600 mSettings.mPermissionTrees.remove(p.info.name);
2601 } else {
2602 mSettings.mPermissions.remove(p.info.name);
2603 }
2604 } else {
2605 bp.perm = null;
2606 }
2607 if (chatty) {
2608 if (r == null) {
2609 r = new StringBuilder(256);
2610 } else {
2611 r.append(' ');
2612 }
2613 r.append(p.info.name);
2614 }
2615 }
2616 }
2617 if (r != null) {
2618 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2619 }
2620
2621 N = pkg.instrumentation.size();
2622 r = null;
2623 for (i=0; i<N; i++) {
2624 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2625 mInstrumentation.remove(a.component);
2626 if (chatty) {
2627 if (r == null) {
2628 r = new StringBuilder(256);
2629 } else {
2630 r.append(' ');
2631 }
2632 r.append(a.info.name);
2633 }
2634 }
2635 if (r != null) {
2636 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2637 }
2638 }
2639 }
2640
2641 private static final boolean isPackageFilename(String name) {
2642 return name != null && name.endsWith(".apk");
2643 }
2644
2645 private void updatePermissionsLP() {
2646 // Make sure there are no dangling permission trees.
2647 Iterator<BasePermission> it = mSettings.mPermissionTrees
2648 .values().iterator();
2649 while (it.hasNext()) {
2650 BasePermission bp = it.next();
2651 if (bp.perm == null) {
2652 Log.w(TAG, "Removing dangling permission tree: " + bp.name
2653 + " from package " + bp.sourcePackage);
2654 it.remove();
2655 }
2656 }
2657
2658 // Make sure all dynamic permissions have been assigned to a package,
2659 // and make sure there are no dangling permissions.
2660 it = mSettings.mPermissions.values().iterator();
2661 while (it.hasNext()) {
2662 BasePermission bp = it.next();
2663 if (bp.type == BasePermission.TYPE_DYNAMIC) {
2664 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
2665 + bp.name + " pkg=" + bp.sourcePackage
2666 + " info=" + bp.pendingInfo);
2667 if (bp.perm == null && bp.pendingInfo != null) {
2668 BasePermission tree = findPermissionTreeLP(bp.name);
2669 if (tree != null) {
2670 bp.perm = new PackageParser.Permission(tree.perm.owner,
2671 new PermissionInfo(bp.pendingInfo));
2672 bp.perm.info.packageName = tree.perm.info.packageName;
2673 bp.perm.info.name = bp.name;
2674 bp.uid = tree.uid;
2675 }
2676 }
2677 }
2678 if (bp.perm == null) {
2679 Log.w(TAG, "Removing dangling permission: " + bp.name
2680 + " from package " + bp.sourcePackage);
2681 it.remove();
2682 }
2683 }
2684
2685 // Now update the permissions for all packages, in particular
2686 // replace the granted permissions of the system packages.
2687 for (PackageParser.Package pkg : mPackages.values()) {
2688 grantPermissionsLP(pkg, false);
2689 }
2690 }
2691
2692 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
2693 final PackageSetting ps = (PackageSetting)pkg.mExtras;
2694 if (ps == null) {
2695 return;
2696 }
2697 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2698 boolean addedPermission = false;
2699
2700 if (replace) {
2701 ps.permissionsFixed = false;
2702 if (gp == ps) {
2703 gp.grantedPermissions.clear();
2704 gp.gids = mGlobalGids;
2705 }
2706 }
2707
2708 if (gp.gids == null) {
2709 gp.gids = mGlobalGids;
2710 }
2711
2712 final int N = pkg.requestedPermissions.size();
2713 for (int i=0; i<N; i++) {
2714 String name = pkg.requestedPermissions.get(i);
2715 BasePermission bp = mSettings.mPermissions.get(name);
2716 PackageParser.Permission p = bp != null ? bp.perm : null;
2717 if (false) {
2718 if (gp != ps) {
2719 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
2720 + ": " + p);
2721 }
2722 }
2723 if (p != null) {
2724 final String perm = p.info.name;
2725 boolean allowed;
2726 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
2727 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
2728 allowed = true;
2729 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
2730 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2731 allowed = (checkSignaturesLP(p.owner, pkg)
2732 == PackageManager.SIGNATURE_MATCH)
2733 || (checkSignaturesLP(mPlatformPackage, pkg)
2734 == PackageManager.SIGNATURE_MATCH);
2735 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2736 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
2737 // For updated system applications, the signatureOrSystem permission
2738 // is granted only if it had been defined by the original application.
2739 if ((pkg.applicationInfo.flags
2740 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
2741 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
2742 if(sysPs.grantedPermissions.contains(perm)) {
2743 allowed = true;
2744 } else {
2745 allowed = false;
2746 }
2747 } else {
2748 allowed = true;
2749 }
2750 }
2751 }
2752 } else {
2753 allowed = false;
2754 }
2755 if (false) {
2756 if (gp != ps) {
2757 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
2758 }
2759 }
2760 if (allowed) {
2761 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
2762 && ps.permissionsFixed) {
2763 // If this is an existing, non-system package, then
2764 // we can't add any new permissions to it.
2765 if (!gp.loadedPermissions.contains(perm)) {
2766 allowed = false;
2767 }
2768 }
2769 if (allowed) {
2770 if (!gp.grantedPermissions.contains(perm)) {
2771 addedPermission = true;
2772 gp.grantedPermissions.add(perm);
2773 gp.gids = appendInts(gp.gids, bp.gids);
2774 }
2775 } else {
2776 Log.w(TAG, "Not granting permission " + perm
2777 + " to package " + pkg.packageName
2778 + " because it was previously installed without");
2779 }
2780 } else {
2781 Log.w(TAG, "Not granting permission " + perm
2782 + " to package " + pkg.packageName
2783 + " (protectionLevel=" + p.info.protectionLevel
2784 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
2785 + ")");
2786 }
2787 } else {
2788 Log.w(TAG, "Unknown permission " + name
2789 + " in package " + pkg.packageName);
2790 }
2791 }
2792
2793 if ((addedPermission || replace) && !ps.permissionsFixed &&
2794 (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2795 // This is the first that we have heard about this package, so the
2796 // permissions we have now selected are fixed until explicitly
2797 // changed.
2798 ps.permissionsFixed = true;
2799 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
2800 }
2801 }
2802
2803 private final class ActivityIntentResolver
2804 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
2805 public List queryIntent(ContentResolver resolver, Intent intent,
2806 String resolvedType, boolean defaultOnly) {
2807 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2808 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2809 }
2810
2811 public List queryIntent(ContentResolver resolver, Intent intent,
2812 String resolvedType, int flags) {
2813 mFlags = flags;
2814 return super.queryIntent(
2815 resolver, intent, resolvedType,
2816 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2817 }
2818
2819 public final void addActivity(PackageParser.Activity a, String type) {
2820 mActivities.put(a.component, a);
2821 if (SHOW_INFO || Config.LOGV) Log.v(
2822 TAG, " " + type + " " +
2823 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2824 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2825 int NI = a.intents.size();
2826 int j;
2827 for (j=0; j<NI; j++) {
2828 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2829 if (SHOW_INFO || Config.LOGV) {
2830 Log.v(TAG, " IntentFilter:");
2831 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2832 }
2833 if (!intent.debugCheck()) {
2834 Log.w(TAG, "==> For Activity " + a.info.name);
2835 }
2836 addFilter(intent);
2837 }
2838 }
2839
2840 public final void removeActivity(PackageParser.Activity a, String type) {
2841 mActivities.remove(a.component);
2842 if (SHOW_INFO || Config.LOGV) Log.v(
2843 TAG, " " + type + " " +
2844 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2845 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2846 int NI = a.intents.size();
2847 int j;
2848 for (j=0; j<NI; j++) {
2849 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2850 if (SHOW_INFO || Config.LOGV) {
2851 Log.v(TAG, " IntentFilter:");
2852 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2853 }
2854 removeFilter(intent);
2855 }
2856 }
2857
2858 @Override
2859 protected boolean allowFilterResult(
2860 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
2861 ActivityInfo filterAi = filter.activity.info;
2862 for (int i=dest.size()-1; i>=0; i--) {
2863 ActivityInfo destAi = dest.get(i).activityInfo;
2864 if (destAi.name == filterAi.name
2865 && destAi.packageName == filterAi.packageName) {
2866 return false;
2867 }
2868 }
2869 return true;
2870 }
2871
2872 @Override
2873 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
2874 int match) {
2875 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
2876 return null;
2877 }
2878 final PackageParser.Activity activity = info.activity;
2879 if (mSafeMode && (activity.info.applicationInfo.flags
2880 &ApplicationInfo.FLAG_SYSTEM) == 0) {
2881 return null;
2882 }
2883 final ResolveInfo res = new ResolveInfo();
2884 res.activityInfo = PackageParser.generateActivityInfo(activity,
2885 mFlags);
2886 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
2887 res.filter = info;
2888 }
2889 res.priority = info.getPriority();
2890 res.preferredOrder = activity.owner.mPreferredOrder;
2891 //System.out.println("Result: " + res.activityInfo.className +
2892 // " = " + res.priority);
2893 res.match = match;
2894 res.isDefault = info.hasDefault;
2895 res.labelRes = info.labelRes;
2896 res.nonLocalizedLabel = info.nonLocalizedLabel;
2897 res.icon = info.icon;
2898 return res;
2899 }
2900
2901 @Override
2902 protected void sortResults(List<ResolveInfo> results) {
2903 Collections.sort(results, mResolvePrioritySorter);
2904 }
2905
2906 @Override
2907 protected void dumpFilter(Printer out, String prefix,
2908 PackageParser.ActivityIntentInfo filter) {
2909 out.println(prefix
2910 + Integer.toHexString(System.identityHashCode(filter.activity))
2911 + " " + filter.activity.component.flattenToShortString());
2912 }
2913
2914// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
2915// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
2916// final List<ResolveInfo> retList = Lists.newArrayList();
2917// while (i.hasNext()) {
2918// final ResolveInfo resolveInfo = i.next();
2919// if (isEnabledLP(resolveInfo.activityInfo)) {
2920// retList.add(resolveInfo);
2921// }
2922// }
2923// return retList;
2924// }
2925
2926 // Keys are String (activity class name), values are Activity.
2927 private final HashMap<ComponentName, PackageParser.Activity> mActivities
2928 = new HashMap<ComponentName, PackageParser.Activity>();
2929 private int mFlags;
2930 }
2931
2932 private final class ServiceIntentResolver
2933 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
2934 public List queryIntent(ContentResolver resolver, Intent intent,
2935 String resolvedType, boolean defaultOnly) {
2936 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2937 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2938 }
2939
2940 public List queryIntent(ContentResolver resolver, Intent intent,
2941 String resolvedType, int flags) {
2942 mFlags = flags;
2943 return super.queryIntent(
2944 resolver, intent, resolvedType,
2945 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2946 }
2947
2948 public final void addService(PackageParser.Service s) {
2949 mServices.put(s.component, s);
2950 if (SHOW_INFO || Config.LOGV) Log.v(
2951 TAG, " " + (s.info.nonLocalizedLabel != null
2952 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2953 if (SHOW_INFO || Config.LOGV) Log.v(
2954 TAG, " Class=" + s.info.name);
2955 int NI = s.intents.size();
2956 int j;
2957 for (j=0; j<NI; j++) {
2958 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
2959 if (SHOW_INFO || Config.LOGV) {
2960 Log.v(TAG, " IntentFilter:");
2961 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2962 }
2963 if (!intent.debugCheck()) {
2964 Log.w(TAG, "==> For Service " + s.info.name);
2965 }
2966 addFilter(intent);
2967 }
2968 }
2969
2970 public final void removeService(PackageParser.Service s) {
2971 mServices.remove(s.component);
2972 if (SHOW_INFO || Config.LOGV) Log.v(
2973 TAG, " " + (s.info.nonLocalizedLabel != null
2974 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2975 if (SHOW_INFO || Config.LOGV) Log.v(
2976 TAG, " Class=" + s.info.name);
2977 int NI = s.intents.size();
2978 int j;
2979 for (j=0; j<NI; j++) {
2980 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
2981 if (SHOW_INFO || Config.LOGV) {
2982 Log.v(TAG, " IntentFilter:");
2983 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2984 }
2985 removeFilter(intent);
2986 }
2987 }
2988
2989 @Override
2990 protected boolean allowFilterResult(
2991 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
2992 ServiceInfo filterSi = filter.service.info;
2993 for (int i=dest.size()-1; i>=0; i--) {
2994 ServiceInfo destAi = dest.get(i).serviceInfo;
2995 if (destAi.name == filterSi.name
2996 && destAi.packageName == filterSi.packageName) {
2997 return false;
2998 }
2999 }
3000 return true;
3001 }
3002
3003 @Override
3004 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3005 int match) {
3006 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3007 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3008 return null;
3009 }
3010 final PackageParser.Service service = info.service;
3011 if (mSafeMode && (service.info.applicationInfo.flags
3012 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3013 return null;
3014 }
3015 final ResolveInfo res = new ResolveInfo();
3016 res.serviceInfo = PackageParser.generateServiceInfo(service,
3017 mFlags);
3018 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3019 res.filter = filter;
3020 }
3021 res.priority = info.getPriority();
3022 res.preferredOrder = service.owner.mPreferredOrder;
3023 //System.out.println("Result: " + res.activityInfo.className +
3024 // " = " + res.priority);
3025 res.match = match;
3026 res.isDefault = info.hasDefault;
3027 res.labelRes = info.labelRes;
3028 res.nonLocalizedLabel = info.nonLocalizedLabel;
3029 res.icon = info.icon;
3030 return res;
3031 }
3032
3033 @Override
3034 protected void sortResults(List<ResolveInfo> results) {
3035 Collections.sort(results, mResolvePrioritySorter);
3036 }
3037
3038 @Override
3039 protected void dumpFilter(Printer out, String prefix,
3040 PackageParser.ServiceIntentInfo filter) {
3041 out.println(prefix
3042 + Integer.toHexString(System.identityHashCode(filter.service))
3043 + " " + filter.service.component.flattenToShortString());
3044 }
3045
3046// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3047// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3048// final List<ResolveInfo> retList = Lists.newArrayList();
3049// while (i.hasNext()) {
3050// final ResolveInfo resolveInfo = (ResolveInfo) i;
3051// if (isEnabledLP(resolveInfo.serviceInfo)) {
3052// retList.add(resolveInfo);
3053// }
3054// }
3055// return retList;
3056// }
3057
3058 // Keys are String (activity class name), values are Activity.
3059 private final HashMap<ComponentName, PackageParser.Service> mServices
3060 = new HashMap<ComponentName, PackageParser.Service>();
3061 private int mFlags;
3062 };
3063
3064 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3065 new Comparator<ResolveInfo>() {
3066 public int compare(ResolveInfo r1, ResolveInfo r2) {
3067 int v1 = r1.priority;
3068 int v2 = r2.priority;
3069 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3070 if (v1 != v2) {
3071 return (v1 > v2) ? -1 : 1;
3072 }
3073 v1 = r1.preferredOrder;
3074 v2 = r2.preferredOrder;
3075 if (v1 != v2) {
3076 return (v1 > v2) ? -1 : 1;
3077 }
3078 if (r1.isDefault != r2.isDefault) {
3079 return r1.isDefault ? -1 : 1;
3080 }
3081 v1 = r1.match;
3082 v2 = r2.match;
3083 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3084 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3085 }
3086 };
3087
3088 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3089 new Comparator<ProviderInfo>() {
3090 public int compare(ProviderInfo p1, ProviderInfo p2) {
3091 final int v1 = p1.initOrder;
3092 final int v2 = p2.initOrder;
3093 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3094 }
3095 };
3096
3097 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3098 IActivityManager am = ActivityManagerNative.getDefault();
3099 if (am != null) {
3100 try {
3101 final Intent intent = new Intent(action,
3102 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3103 if (extras != null) {
3104 intent.putExtras(extras);
3105 }
3106 am.broadcastIntent(
3107 null, intent,
3108 null, null, 0, null, null, null, false, false);
3109 } catch (RemoteException ex) {
3110 }
3111 }
3112 }
3113
3114 private final class AppDirObserver extends FileObserver {
3115 public AppDirObserver(String path, int mask, boolean isrom) {
3116 super(path, mask);
3117 mRootDir = path;
3118 mIsRom = isrom;
3119 }
3120
3121 public void onEvent(int event, String path) {
3122 String removedPackage = null;
3123 int removedUid = -1;
3124 String addedPackage = null;
3125 int addedUid = -1;
3126
3127 synchronized (mInstallLock) {
3128 String fullPathStr = null;
3129 File fullPath = null;
3130 if (path != null) {
3131 fullPath = new File(mRootDir, path);
3132 fullPathStr = fullPath.getPath();
3133 }
3134
3135 if (Config.LOGV) Log.v(
3136 TAG, "File " + fullPathStr + " changed: "
3137 + Integer.toHexString(event));
3138
3139 if (!isPackageFilename(path)) {
3140 if (Config.LOGV) Log.v(
3141 TAG, "Ignoring change of non-package file: " + fullPathStr);
3142 return;
3143 }
3144
3145 if ((event&REMOVE_EVENTS) != 0) {
3146 synchronized (mInstallLock) {
3147 PackageParser.Package p = mAppDirs.get(fullPathStr);
3148 if (p != null) {
3149 removePackageLI(p, true);
3150 removedPackage = p.applicationInfo.packageName;
3151 removedUid = p.applicationInfo.uid;
3152 }
3153 }
3154 }
3155
3156 if ((event&ADD_EVENTS) != 0) {
3157 PackageParser.Package p = mAppDirs.get(fullPathStr);
3158 if (p == null) {
3159 p = scanPackageLI(fullPath, fullPath, fullPath,
3160 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3161 PackageParser.PARSE_CHATTY |
3162 PackageParser.PARSE_MUST_BE_APK,
3163 SCAN_MONITOR);
3164 if (p != null) {
3165 synchronized (mPackages) {
3166 grantPermissionsLP(p, false);
3167 }
3168 addedPackage = p.applicationInfo.packageName;
3169 addedUid = p.applicationInfo.uid;
3170 }
3171 }
3172 }
3173
3174 synchronized (mPackages) {
3175 mSettings.writeLP();
3176 }
3177 }
3178
3179 if (removedPackage != null) {
3180 Bundle extras = new Bundle(1);
3181 extras.putInt(Intent.EXTRA_UID, removedUid);
3182 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3183 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3184 }
3185 if (addedPackage != null) {
3186 Bundle extras = new Bundle(1);
3187 extras.putInt(Intent.EXTRA_UID, addedUid);
3188 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3189 }
3190 }
3191
3192 private final String mRootDir;
3193 private final boolean mIsRom;
3194 }
3195
3196 /* Called when a downloaded package installation has been confirmed by the user */
3197 public void installPackage(
3198 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
3199 mContext.enforceCallingOrSelfPermission(
3200 android.Manifest.permission.INSTALL_PACKAGES, null);
3201
3202 // Queue up an async operation since the package installation may take a little while.
3203 mHandler.post(new Runnable() {
3204 public void run() {
3205 mHandler.removeCallbacks(this);
3206 PackageInstalledInfo res;
3207 synchronized (mInstallLock) {
3208 res = installPackageLI(packageURI, flags);
3209 }
3210 if (observer != null) {
3211 try {
3212 observer.packageInstalled(res.name, res.returnCode);
3213 } catch (RemoteException e) {
3214 Log.i(TAG, "Observer no longer exists.");
3215 }
3216 }
3217 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3218 // call appears in the synchronized block above.
3219 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3220 res.removedInfo.sendBroadcast(false, true);
3221 Bundle extras = new Bundle(1);
3222 extras.putInt(Intent.EXTRA_UID, res.uid);
3223 if (res.removedInfo.removedPackage != null) {
3224 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3225 }
3226 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3227 res.pkg.applicationInfo.packageName,
3228 extras);
3229 }
3230 Runtime.getRuntime().gc();
3231 }
3232 });
3233 }
3234
3235 class PackageInstalledInfo {
3236 String name;
3237 int uid;
3238 PackageParser.Package pkg;
3239 int returnCode;
3240 PackageRemovedInfo removedInfo;
3241 }
3242
3243 /*
3244 * Install a non-existing package.
3245 */
3246 private void installNewPackageLI(String pkgName,
3247 File tmpPackageFile,
3248 String destFilePath, File destPackageFile, File destResourceFile,
3249 PackageParser.Package pkg, boolean forwardLocked,
3250 PackageInstalledInfo res) {
3251 // Remember this for later, in case we need to rollback this install
3252 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3253 res.name = pkgName;
3254 synchronized(mPackages) {
3255 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3256 // Don't allow installation over an existing package with the same name.
3257 Log.w(TAG, "Attempt to re-install " + pkgName
3258 + " without first uninstalling.");
3259 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3260 return;
3261 }
3262 }
3263 if (destPackageFile.exists()) {
3264 // It's safe to do this because we know (from the above check) that the file
3265 // isn't currently used for an installed package.
3266 destPackageFile.delete();
3267 }
3268 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3269 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3270 destResourceFile, pkg, 0,
3271 SCAN_MONITOR | SCAN_FORCE_DEX
3272 | SCAN_UPDATE_SIGNATURE
3273 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
3274 if (newPackage == null) {
3275 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3276 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3277 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3278 }
3279 } else {
3280 updateSettingsLI(pkgName, tmpPackageFile,
3281 destFilePath, destPackageFile,
3282 destResourceFile, pkg,
3283 newPackage,
3284 true,
3285 forwardLocked,
3286 res);
3287 // delete the partially installed application. the data directory will have to be
3288 // restored if it was already existing
3289 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3290 // remove package from internal structures. Note that we want deletePackageX to
3291 // delete the package data and cache directories that it created in
3292 // scanPackageLocked, unless those directories existed before we even tried to
3293 // install.
3294 deletePackageLI(
3295 pkgName, true,
3296 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3297 res.removedInfo);
3298 }
3299 }
3300 }
3301
3302 private void replacePackageLI(String pkgName,
3303 File tmpPackageFile,
3304 String destFilePath, File destPackageFile, File destResourceFile,
3305 PackageParser.Package pkg, boolean forwardLocked,
3306 PackageInstalledInfo res) {
3307 PackageParser.Package deletedPackage;
3308 // First find the old package info and check signatures
3309 synchronized(mPackages) {
3310 deletedPackage = mPackages.get(pkgName);
3311 if(checkSignaturesLP(pkg, deletedPackage) != PackageManager.SIGNATURE_MATCH) {
3312 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3313 return;
3314 }
3315 }
3316 boolean sysPkg = ((deletedPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
3317 if(sysPkg) {
3318 replaceSystemPackageLI(deletedPackage,
3319 tmpPackageFile, destFilePath,
3320 destPackageFile, destResourceFile, pkg, forwardLocked, res);
3321 } else {
3322 replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath,
3323 destPackageFile, destResourceFile, pkg, forwardLocked, res);
3324 }
3325 }
3326
3327 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3328 File tmpPackageFile,
3329 String destFilePath, File destPackageFile, File destResourceFile,
3330 PackageParser.Package pkg, boolean forwardLocked,
3331 PackageInstalledInfo res) {
3332 PackageParser.Package newPackage = null;
3333 String pkgName = deletedPackage.packageName;
3334 boolean deletedPkg = true;
3335 boolean updatedSettings = false;
3336 int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
3337 // First delete the existing package while retaining the data directory
3338 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3339 res.removedInfo)) {
3340 // If the existing package was'nt successfully deleted
3341 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3342 deletedPkg = false;
3343 } else {
3344 // Successfully deleted the old package. Now proceed with re-installation
3345 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3346 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3347 destResourceFile, pkg, parseFlags,
3348 SCAN_MONITOR | SCAN_FORCE_DEX
3349 | SCAN_UPDATE_SIGNATURE
3350 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
3351 if (newPackage == null) {
3352 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3353 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3354 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3355 }
3356 } else {
3357 updateSettingsLI(pkgName, tmpPackageFile,
3358 destFilePath, destPackageFile,
3359 destResourceFile, pkg,
3360 newPackage,
3361 true,
3362 forwardLocked,
3363 res);
3364 updatedSettings = true;
3365 }
3366 }
3367
3368 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3369 // If we deleted an exisiting package, the old source and resource files that we
3370 // were keeping around in case we needed them (see below) can now be deleted
3371 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3372 final ApplicationInfo installedPackageAppInfo =
3373 newPackage.applicationInfo;
3374 if (!deletedPackageAppInfo.sourceDir
3375 .equals(installedPackageAppInfo.sourceDir)) {
3376 new File(deletedPackageAppInfo.sourceDir).delete();
3377 }
3378 if (!deletedPackageAppInfo.publicSourceDir
3379 .equals(installedPackageAppInfo.publicSourceDir)) {
3380 new File(deletedPackageAppInfo.publicSourceDir).delete();
3381 }
3382 //update signature on the new package setting
3383 //this should always succeed, since we checked the
3384 //signature earlier.
3385 synchronized(mPackages) {
3386 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3387 parseFlags, true);
3388 }
3389 } else {
3390 // remove package from internal structures. Note that we want deletePackageX to
3391 // delete the package data and cache directories that it created in
3392 // scanPackageLocked, unless those directories existed before we even tried to
3393 // install.
3394 if(updatedSettings) {
3395 deletePackageLI(
3396 pkgName, true,
3397 PackageManager.DONT_DELETE_DATA,
3398 res.removedInfo);
3399 }
3400 // Since we failed to install the new package we need to restore the old
3401 // package that we deleted.
3402 if(deletedPkg) {
3403 installPackageLI(
3404 Uri.fromFile(new File(deletedPackage.mPath)),
3405 isForwardLocked(deletedPackage)
3406 ? PackageManager.FORWARD_LOCK_PACKAGE
3407 : 0);
3408 }
3409 }
3410 }
3411
3412 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3413 File tmpPackageFile,
3414 String destFilePath, File destPackageFile, File destResourceFile,
3415 PackageParser.Package pkg, boolean forwardLocked,
3416 PackageInstalledInfo res) {
3417 PackageParser.Package newPackage = null;
3418 boolean updatedSettings = false;
3419 int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
3420 PackageParser.PARSE_IS_SYSTEM;
3421 String packageName = deletedPackage.packageName;
3422 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3423 if (packageName == null) {
3424 Log.w(TAG, "Attempt to delete null packageName.");
3425 return;
3426 }
3427 PackageParser.Package oldPkg;
3428 PackageSetting oldPkgSetting;
3429 synchronized (mPackages) {
3430 oldPkg = mPackages.get(packageName);
3431 oldPkgSetting = mSettings.mPackages.get(packageName);
3432 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3433 (oldPkgSetting == null)) {
3434 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3435 return;
3436 }
3437 }
3438 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3439 res.removedInfo.removedPackage = packageName;
3440 // Remove existing system package
3441 removePackageLI(oldPkg, true);
3442 synchronized (mPackages) {
3443 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3444 }
3445
3446 // Successfully disabled the old package. Now proceed with re-installation
3447 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3448 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3449 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3450 destResourceFile, pkg, parseFlags,
3451 SCAN_MONITOR | SCAN_FORCE_DEX
3452 | SCAN_UPDATE_SIGNATURE
3453 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
3454 if (newPackage == null) {
3455 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3456 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3457 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3458 }
3459 } else {
3460 updateSettingsLI(packageName, tmpPackageFile,
3461 destFilePath, destPackageFile,
3462 destResourceFile, pkg,
3463 newPackage,
3464 true,
3465 forwardLocked,
3466 res);
3467 updatedSettings = true;
3468 }
3469
3470 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3471 //update signature on the new package setting
3472 //this should always succeed, since we checked the
3473 //signature earlier.
3474 synchronized(mPackages) {
3475 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3476 parseFlags, true);
3477 }
3478 } else {
3479 // Re installation failed. Restore old information
3480 // Remove new pkg information
3481 removePackageLI(newPackage, true);
3482 // Add back the old system package
3483 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3484 oldPkgSetting.resourcePath,
3485 oldPkg, parseFlags,
3486 SCAN_MONITOR
3487 | SCAN_UPDATE_SIGNATURE
3488 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
3489 // Restore the old system information in Settings
3490 synchronized(mPackages) {
3491 if(updatedSettings) {
3492 mSettings.enableSystemPackageLP(packageName);
3493 }
3494 mSettings.writeLP();
3495 }
3496 }
3497 }
3498
3499 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3500 String destFilePath, File destPackageFile,
3501 File destResourceFile,
3502 PackageParser.Package pkg,
3503 PackageParser.Package newPackage,
3504 boolean replacingExistingPackage,
3505 boolean forwardLocked,
3506 PackageInstalledInfo res) {
3507 synchronized (mPackages) {
3508 //write settings. the installStatus will be incomplete at this stage.
3509 //note that the new package setting would have already been
3510 //added to mPackages. It hasn't been persisted yet.
3511 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3512 mSettings.writeLP();
3513 }
3514
3515 int retCode = 0;
3516 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3517 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3518 destPackageFile.toString());
3519 if (retCode != 0) {
3520 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3521 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3522 return;
3523 }
3524 }
3525 // XXX There are probably some big issues here: upon doing
3526 // the rename, we have reached the point of no return (the
3527 // original .apk is gone!), so we can't fail. Yet... we can.
3528 if (!tmpPackageFile.renameTo(destPackageFile)) {
3529 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3530 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3531 } else {
3532 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
3533 destResourceFile,
3534 forwardLocked);
3535 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3536 return;
3537 } else {
3538 Log.d(TAG, "New package installed in " + destPackageFile);
3539 }
3540 }
3541 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3542 if (mInstaller != null) {
3543 mInstaller.rmdex(tmpPackageFile.getPath());
3544 }
3545 }
3546
3547 synchronized (mPackages) {
3548 grantPermissionsLP(newPackage, true);
3549 res.name = pkgName;
3550 res.uid = newPackage.applicationInfo.uid;
3551 res.pkg = newPackage;
3552 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
3553 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3554 //to update install status
3555 mSettings.writeLP();
3556 }
3557 }
3558
3559 private PackageInstalledInfo installPackageLI(Uri pPackageURI, int pFlags) {
3560 File tmpPackageFile = null;
3561 String pkgName = null;
3562 boolean forwardLocked = false;
3563 boolean replacingExistingPackage = false;
3564 // Result object to be returned
3565 PackageInstalledInfo res = new PackageInstalledInfo();
3566 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3567 res.uid = -1;
3568 res.pkg = null;
3569 res.removedInfo = new PackageRemovedInfo();
3570
3571 main_flow: try {
3572 tmpPackageFile = createTempPackageFile();
3573 if (tmpPackageFile == null) {
3574 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3575 break main_flow;
3576 }
3577 tmpPackageFile.deleteOnExit(); // paranoia
3578 if (pPackageURI.getScheme().equals("file")) {
3579 final File srcPackageFile = new File(pPackageURI.getPath());
3580 // We copy the source package file to a temp file and then rename it to the
3581 // destination file in order to eliminate a window where the package directory
3582 // scanner notices the new package file but it's not completely copied yet.
3583 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3584 Log.e(TAG, "Couldn't copy package file to temp file.");
3585 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3586 break main_flow;
3587 }
3588 } else if (pPackageURI.getScheme().equals("content")) {
3589 ParcelFileDescriptor fd;
3590 try {
3591 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
3592 } catch (FileNotFoundException e) {
3593 Log.e(TAG, "Couldn't open file descriptor from download service.");
3594 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3595 break main_flow;
3596 }
3597 if (fd == null) {
3598 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3599 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3600 break main_flow;
3601 }
3602 if (Config.LOGV) {
3603 Log.v(TAG, "Opened file descriptor from download service.");
3604 }
3605 ParcelFileDescriptor.AutoCloseInputStream
3606 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3607 // We copy the source package file to a temp file and then rename it to the
3608 // destination file in order to eliminate a window where the package directory
3609 // scanner notices the new package file but it's not completely copied yet.
3610 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3611 Log.e(TAG, "Couldn't copy package stream to temp file.");
3612 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3613 break main_flow;
3614 }
3615 } else {
3616 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
3617 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3618 break main_flow;
3619 }
3620 pkgName = PackageParser.parsePackageName(
3621 tmpPackageFile.getAbsolutePath(), 0);
3622 if (pkgName == null) {
3623 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3624 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3625 break main_flow;
3626 }
3627 res.name = pkgName;
3628 //initialize some variables before installing pkg
3629 final String pkgFileName = pkgName + ".apk";
3630 final File destDir = ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
3631 ? mDrmAppPrivateInstallDir
3632 : mAppInstallDir;
3633 final File destPackageFile = new File(destDir, pkgFileName);
3634 final String destFilePath = destPackageFile.getAbsolutePath();
3635 File destResourceFile;
3636 if ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
3637 final String publicZipFileName = pkgName + ".zip";
3638 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3639 forwardLocked = true;
3640 } else {
3641 destResourceFile = destPackageFile;
3642 }
3643 // Retrieve PackageSettings and parse package
3644 int parseFlags = PackageParser.PARSE_CHATTY;
3645 parseFlags |= mDefParseFlags;
3646 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3647 pp.setSeparateProcesses(mSeparateProcesses);
3648 pp.setSdkVersion(mSdkVersion);
3649 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3650 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3651 if (pkg == null) {
3652 res.returnCode = pp.getParseError();
3653 break main_flow;
3654 }
3655 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3656 res.returnCode = pp.getParseError();
3657 break main_flow;
3658 }
3659
3660 synchronized (mPackages) {
3661 //check if installing already existing package
3662 if ((pFlags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
3663 && mPackages.containsKey(pkgName)) {
3664 replacingExistingPackage = true;
3665 }
3666 }
3667
3668 if(replacingExistingPackage) {
3669 replacePackageLI(pkgName,
3670 tmpPackageFile,
3671 destFilePath, destPackageFile, destResourceFile,
3672 pkg, forwardLocked,
3673 res);
3674 } else {
3675 installNewPackageLI(pkgName,
3676 tmpPackageFile,
3677 destFilePath, destPackageFile, destResourceFile,
3678 pkg, forwardLocked,
3679 res);
3680 }
3681 } finally {
3682 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3683 tmpPackageFile.delete();
3684 }
3685 return res;
3686 }
3687 }
3688
3689 private int setPermissionsLI(String pkgName,
3690 PackageParser.Package newPackage,
3691 String destFilePath,
3692 File destResourceFile,
3693 boolean forwardLocked) {
3694 int retCode;
3695 if (forwardLocked) {
3696 try {
3697 extractPublicFiles(newPackage, destResourceFile);
3698 } catch (IOException e) {
3699 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3700 " forward-locked app.");
3701 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3702 } finally {
3703 //TODO clean up the extracted public files
3704 }
3705 if (mInstaller != null) {
3706 retCode = mInstaller.setForwardLockPerm(pkgName,
3707 newPackage.applicationInfo.uid);
3708 } else {
3709 final int filePermissions =
3710 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3711 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3712 newPackage.applicationInfo.uid);
3713 }
3714 } else {
3715 final int filePermissions =
3716 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3717 |FileUtils.S_IROTH;
3718 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3719 }
3720 if (retCode != 0) {
3721 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3722 + ". The return code was: " + retCode);
3723 }
3724 return PackageManager.INSTALL_SUCCEEDED;
3725 }
3726
3727 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3728 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3729 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3730 }
3731
3732 private void extractPublicFiles(PackageParser.Package newPackage,
3733 File publicZipFile) throws IOException {
3734 final ZipOutputStream publicZipOutStream =
3735 new ZipOutputStream(new FileOutputStream(publicZipFile));
3736 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3737
3738 // Copy manifest, resources.arsc and res directory to public zip
3739
3740 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3741 while (privateZipEntries.hasMoreElements()) {
3742 final ZipEntry zipEntry = privateZipEntries.nextElement();
3743 final String zipEntryName = zipEntry.getName();
3744 if ("AndroidManifest.xml".equals(zipEntryName)
3745 || "resources.arsc".equals(zipEntryName)
3746 || zipEntryName.startsWith("res/")) {
3747 try {
3748 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3749 } catch (IOException e) {
3750 try {
3751 publicZipOutStream.close();
3752 throw e;
3753 } finally {
3754 publicZipFile.delete();
3755 }
3756 }
3757 }
3758 }
3759
3760 publicZipOutStream.close();
3761 FileUtils.setPermissions(
3762 publicZipFile.getAbsolutePath(),
3763 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
3764 -1, -1);
3765 }
3766
3767 private static void copyZipEntry(ZipEntry zipEntry,
3768 ZipFile inZipFile,
3769 ZipOutputStream outZipStream) throws IOException {
3770 byte[] buffer = new byte[4096];
3771 int num;
3772
3773 ZipEntry newEntry;
3774 if (zipEntry.getMethod() == ZipEntry.STORED) {
3775 // Preserve the STORED method of the input entry.
3776 newEntry = new ZipEntry(zipEntry);
3777 } else {
3778 // Create a new entry so that the compressed len is recomputed.
3779 newEntry = new ZipEntry(zipEntry.getName());
3780 }
3781 outZipStream.putNextEntry(newEntry);
3782
3783 InputStream data = inZipFile.getInputStream(zipEntry);
3784 while ((num = data.read(buffer)) > 0) {
3785 outZipStream.write(buffer, 0, num);
3786 }
3787 outZipStream.flush();
3788 }
3789
3790 private void deleteTempPackageFiles() {
3791 FilenameFilter filter = new FilenameFilter() {
3792 public boolean accept(File dir, String name) {
3793 return name.startsWith("vmdl") && name.endsWith(".tmp");
3794 }
3795 };
3796 String tmpFilesList[] = mAppInstallDir.list(filter);
3797 if(tmpFilesList == null) {
3798 return;
3799 }
3800 for(int i = 0; i < tmpFilesList.length; i++) {
3801 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
3802 tmpFile.delete();
3803 }
3804 }
3805
3806 private File createTempPackageFile() {
3807 File tmpPackageFile;
3808 try {
3809 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
3810 } catch (IOException e) {
3811 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
3812 return null;
3813 }
3814 try {
3815 FileUtils.setPermissions(
3816 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
3817 -1, -1);
3818 } catch (IOException e) {
3819 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
3820 return null;
3821 }
3822 return tmpPackageFile;
3823 }
3824
3825 public void deletePackage(final String packageName,
3826 final IPackageDeleteObserver observer,
3827 final int flags) {
3828 mContext.enforceCallingOrSelfPermission(
3829 android.Manifest.permission.DELETE_PACKAGES, null);
3830 // Queue up an async operation since the package deletion may take a little while.
3831 mHandler.post(new Runnable() {
3832 public void run() {
3833 mHandler.removeCallbacks(this);
3834 final boolean succeded = deletePackageX(packageName, true, true, flags);
3835 if (observer != null) {
3836 try {
3837 observer.packageDeleted(succeded);
3838 } catch (RemoteException e) {
3839 Log.i(TAG, "Observer no longer exists.");
3840 } //end catch
3841 } //end if
3842 } //end run
3843 });
3844 }
3845
3846 /**
3847 * This method is an internal method that could be get invoked either
3848 * to delete an installed package or to clean up a failed installation.
3849 * After deleting an installed package, a broadcast is sent to notify any
3850 * listeners that the package has been installed. For cleaning up a failed
3851 * installation, the broadcast is not necessary since the package's
3852 * installation wouldn't have sent the initial broadcast either
3853 * The key steps in deleting a package are
3854 * deleting the package information in internal structures like mPackages,
3855 * deleting the packages base directories through installd
3856 * updating mSettings to reflect current status
3857 * persisting settings for later use
3858 * sending a broadcast if necessary
3859 */
3860
3861 private boolean deletePackageX(String packageName, boolean sendBroadCast,
3862 boolean deleteCodeAndResources, int flags) {
3863 PackageRemovedInfo info = new PackageRemovedInfo();
3864 boolean res = false;
3865
3866 synchronized (mInstallLock) {
3867 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
3868 }
3869
3870 if(res && sendBroadCast) {
3871 info.sendBroadcast(deleteCodeAndResources, false);
3872 }
3873 return res;
3874 }
3875
3876 static class PackageRemovedInfo {
3877 String removedPackage;
3878 int uid = -1;
3879 int removedUid = -1;
3880
3881 void sendBroadcast(boolean fullRemove, boolean replacing) {
3882 Bundle extras = new Bundle(1);
3883 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
3884 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
3885 if (replacing) {
3886 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3887 }
3888 if (removedPackage != null) {
3889 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3890 }
3891 if (removedUid >= 0) {
3892 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
3893 }
3894 }
3895 }
3896
3897 /*
3898 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
3899 * flag is not set, the data directory is removed as well.
3900 * make sure this flag is set for partially installed apps. If not its meaningless to
3901 * delete a partially installed application.
3902 */
3903 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
3904 int flags) {
3905 String packageName = p.packageName;
3906 outInfo.removedPackage = packageName;
3907 removePackageLI(p, true);
3908 // Retrieve object to delete permissions for shared user later on
3909 PackageSetting deletedPs;
3910 synchronized (mPackages) {
3911 deletedPs = mSettings.mPackages.get(packageName);
3912 }
3913 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
3914 if (mInstaller != null) {
3915 int retCode = mInstaller.remove(packageName);
3916 if (retCode < 0) {
3917 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
3918 + packageName + ", retcode=" + retCode);
3919 // we don't consider this to be a failure of the core package deletion
3920 }
3921 } else {
3922 //for emulator
3923 PackageParser.Package pkg = mPackages.get(packageName);
3924 File dataDir = new File(pkg.applicationInfo.dataDir);
3925 dataDir.delete();
3926 }
3927 synchronized (mPackages) {
3928 outInfo.removedUid = mSettings.removePackageLP(packageName);
3929 }
3930 }
3931 synchronized (mPackages) {
3932 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
3933 // remove permissions associated with package
3934 mSettings.updateSharedUserPerms (deletedPs);
3935 }
3936 // Save settings now
3937 mSettings.writeLP ();
3938 }
3939 }
3940
3941 /*
3942 * Tries to delete system package.
3943 */
3944 private boolean deleteSystemPackageLI(PackageParser.Package p,
3945 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
3946 ApplicationInfo applicationInfo = p.applicationInfo;
3947 //applicable for non-partially installed applications only
3948 if (applicationInfo == null) {
3949 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
3950 return false;
3951 }
3952 PackageSetting ps = null;
3953 // Confirm if the system package has been updated
3954 // An updated system app can be deleted. This will also have to restore
3955 // the system pkg from system partition
3956 synchronized (mPackages) {
3957 ps = mSettings.getDisabledSystemPkg(p.packageName);
3958 }
3959 if (ps == null) {
3960 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
3961 return false;
3962 } else {
3963 Log.i(TAG, "Deleting system pkg from data partition");
3964 }
3965 // Delete the updated package
3966 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
3967 if (!ret) {
3968 return false;
3969 }
3970 synchronized (mPackages) {
3971 // Reinstate the old system package
3972 mSettings.enableSystemPackageLP(p.packageName);
3973 }
3974 // Install the system package
3975 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
3976 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
3977 SCAN_MONITOR);
3978
3979 if (newPkg == null) {
3980 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
3981 return false;
3982 }
3983 synchronized (mPackages) {
3984 mSettings.writeLP();
3985 }
3986 return true;
3987 }
3988
3989 private boolean deleteInstalledPackageLI(PackageParser.Package p,
3990 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
3991 ApplicationInfo applicationInfo = p.applicationInfo;
3992 if (applicationInfo == null) {
3993 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
3994 return false;
3995 }
3996 // Delete application's source directory
3997 File sourceFile = new File(applicationInfo.sourceDir);
3998 if (!sourceFile.exists()) {
3999 Log.w(TAG, "Package source " + applicationInfo.sourceDir + " does not exist.");
4000 }
4001 outInfo.uid = applicationInfo.uid;
4002
4003 // Delete package data from internal structures and also remove data if flag is set
4004 removePackageDataLI(p, outInfo, flags);
4005
4006 // Delete application code and resources
4007 if (deleteCodeAndResources) {
4008 sourceFile.delete();
4009 final File publicSourceFile = new File(applicationInfo.publicSourceDir);
4010 if (publicSourceFile.exists()) {
4011 publicSourceFile.delete();
4012 }
4013 if (mInstaller != null) {
4014 int retCode = mInstaller.rmdex(sourceFile.toString());
4015 if (retCode < 0) {
4016 Log.w(TAG, "Couldn't remove dex file for package: "
4017 + p.packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4018 // we don't consider this to be a failure of the core package deletion
4019 }
4020 }
4021 }
4022 return true;
4023 }
4024
4025 /*
4026 * This method handles package deletion in general
4027 */
4028 private boolean deletePackageLI(String packageName,
4029 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4030 if (packageName == null) {
4031 Log.w(TAG, "Attempt to delete null packageName.");
4032 return false;
4033 }
4034 PackageParser.Package p;
4035 boolean dataOnly = false;
4036 synchronized (mPackages) {
4037 p = mPackages.get(packageName);
4038 if (p == null) {
4039 //this retrieves partially installed apps
4040 dataOnly = true;
4041 PackageSetting ps = mSettings.mPackages.get(packageName);
4042 if (ps == null) {
4043 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4044 return false;
4045 }
4046 p = ps.pkg;
4047 }
4048 }
4049 if (p == null) {
4050 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4051 return false;
4052 }
4053
4054 if (dataOnly) {
4055 // Delete application data first
4056 removePackageDataLI(p, outInfo, flags);
4057 return true;
4058 }
4059 // At this point the package should have ApplicationInfo associated with it
4060 if (p.applicationInfo == null) {
4061 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4062 return false;
4063 }
4064 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4065 Log.i(TAG, "Removing system package:"+p.packageName);
4066 // When an updated system application is deleted we delete the existing resources as well and
4067 // fall back to existing code in system partition
4068 return deleteSystemPackageLI(p, true, flags, outInfo);
4069 }
4070 Log.i(TAG, "Removing non-system package:"+p.packageName);
4071 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4072 }
4073
4074 public void clearApplicationUserData(final String packageName,
4075 final IPackageDataObserver observer) {
4076 mContext.enforceCallingOrSelfPermission(
4077 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4078 // Queue up an async operation since the package deletion may take a little while.
4079 mHandler.post(new Runnable() {
4080 public void run() {
4081 mHandler.removeCallbacks(this);
4082 final boolean succeeded;
4083 synchronized (mInstallLock) {
4084 succeeded = clearApplicationUserDataLI(packageName);
4085 }
4086 if (succeeded) {
4087 // invoke DeviceStorageMonitor's update method to clear any notifications
4088 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4089 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4090 if (dsm != null) {
4091 dsm.updateMemory();
4092 }
4093 }
4094 if(observer != null) {
4095 try {
4096 observer.onRemoveCompleted(packageName, succeeded);
4097 } catch (RemoteException e) {
4098 Log.i(TAG, "Observer no longer exists.");
4099 }
4100 } //end if observer
4101 } //end run
4102 });
4103 }
4104
4105 private boolean clearApplicationUserDataLI(String packageName) {
4106 if (packageName == null) {
4107 Log.w(TAG, "Attempt to delete null packageName.");
4108 return false;
4109 }
4110 PackageParser.Package p;
4111 boolean dataOnly = false;
4112 synchronized (mPackages) {
4113 p = mPackages.get(packageName);
4114 if(p == null) {
4115 dataOnly = true;
4116 PackageSetting ps = mSettings.mPackages.get(packageName);
4117 if((ps == null) || (ps.pkg == null)) {
4118 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4119 return false;
4120 }
4121 p = ps.pkg;
4122 }
4123 }
4124 if(!dataOnly) {
4125 //need to check this only for fully installed applications
4126 if (p == null) {
4127 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4128 return false;
4129 }
4130 final ApplicationInfo applicationInfo = p.applicationInfo;
4131 if (applicationInfo == null) {
4132 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4133 return false;
4134 }
4135 }
4136 if (mInstaller != null) {
4137 int retCode = mInstaller.clearUserData(packageName);
4138 if (retCode < 0) {
4139 Log.w(TAG, "Couldn't remove cache files for package: "
4140 + packageName);
4141 return false;
4142 }
4143 }
4144 return true;
4145 }
4146
4147 public void deleteApplicationCacheFiles(final String packageName,
4148 final IPackageDataObserver observer) {
4149 mContext.enforceCallingOrSelfPermission(
4150 android.Manifest.permission.DELETE_CACHE_FILES, null);
4151 // Queue up an async operation since the package deletion may take a little while.
4152 mHandler.post(new Runnable() {
4153 public void run() {
4154 mHandler.removeCallbacks(this);
4155 final boolean succeded;
4156 synchronized (mInstallLock) {
4157 succeded = deleteApplicationCacheFilesLI(packageName);
4158 }
4159 if(observer != null) {
4160 try {
4161 observer.onRemoveCompleted(packageName, succeded);
4162 } catch (RemoteException e) {
4163 Log.i(TAG, "Observer no longer exists.");
4164 }
4165 } //end if observer
4166 } //end run
4167 });
4168 }
4169
4170 private boolean deleteApplicationCacheFilesLI(String packageName) {
4171 if (packageName == null) {
4172 Log.w(TAG, "Attempt to delete null packageName.");
4173 return false;
4174 }
4175 PackageParser.Package p;
4176 synchronized (mPackages) {
4177 p = mPackages.get(packageName);
4178 }
4179 if (p == null) {
4180 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4181 return false;
4182 }
4183 final ApplicationInfo applicationInfo = p.applicationInfo;
4184 if (applicationInfo == null) {
4185 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4186 return false;
4187 }
4188 if (mInstaller != null) {
4189 int retCode = mInstaller.deleteCacheFiles(packageName);
4190 if (retCode < 0) {
4191 Log.w(TAG, "Couldn't remove cache files for package: "
4192 + packageName);
4193 return false;
4194 }
4195 }
4196 return true;
4197 }
4198
4199 public void getPackageSizeInfo(final String packageName,
4200 final IPackageStatsObserver observer) {
4201 mContext.enforceCallingOrSelfPermission(
4202 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4203 // Queue up an async operation since the package deletion may take a little while.
4204 mHandler.post(new Runnable() {
4205 public void run() {
4206 mHandler.removeCallbacks(this);
4207 PackageStats lStats = new PackageStats(packageName);
4208 final boolean succeded;
4209 synchronized (mInstallLock) {
4210 succeded = getPackageSizeInfoLI(packageName, lStats);
4211 }
4212 if(observer != null) {
4213 try {
4214 observer.onGetStatsCompleted(lStats, succeded);
4215 } catch (RemoteException e) {
4216 Log.i(TAG, "Observer no longer exists.");
4217 }
4218 } //end if observer
4219 } //end run
4220 });
4221 }
4222
4223 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4224 if (packageName == null) {
4225 Log.w(TAG, "Attempt to get size of null packageName.");
4226 return false;
4227 }
4228 PackageParser.Package p;
4229 boolean dataOnly = false;
4230 synchronized (mPackages) {
4231 p = mPackages.get(packageName);
4232 if(p == null) {
4233 dataOnly = true;
4234 PackageSetting ps = mSettings.mPackages.get(packageName);
4235 if((ps == null) || (ps.pkg == null)) {
4236 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4237 return false;
4238 }
4239 p = ps.pkg;
4240 }
4241 }
4242 String publicSrcDir = null;
4243 if(!dataOnly) {
4244 final ApplicationInfo applicationInfo = p.applicationInfo;
4245 if (applicationInfo == null) {
4246 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4247 return false;
4248 }
4249 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4250 }
4251 if (mInstaller != null) {
4252 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4253 publicSrcDir, pStats);
4254 if (res < 0) {
4255 return false;
4256 } else {
4257 return true;
4258 }
4259 }
4260 return true;
4261 }
4262
4263
4264 public void addPackageToPreferred(String packageName) {
4265 mContext.enforceCallingOrSelfPermission(
4266 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4267
4268 synchronized (mPackages) {
4269 PackageParser.Package p = mPackages.get(packageName);
4270 if (p == null) {
4271 return;
4272 }
4273 PackageSetting ps = (PackageSetting)p.mExtras;
4274 if (ps != null) {
4275 mSettings.mPreferredPackages.remove(ps);
4276 mSettings.mPreferredPackages.add(0, ps);
4277 updatePreferredIndicesLP();
4278 mSettings.writeLP();
4279 }
4280 }
4281 }
4282
4283 public void removePackageFromPreferred(String packageName) {
4284 mContext.enforceCallingOrSelfPermission(
4285 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4286
4287 synchronized (mPackages) {
4288 PackageParser.Package p = mPackages.get(packageName);
4289 if (p == null) {
4290 return;
4291 }
4292 if (p.mPreferredOrder > 0) {
4293 PackageSetting ps = (PackageSetting)p.mExtras;
4294 if (ps != null) {
4295 mSettings.mPreferredPackages.remove(ps);
4296 p.mPreferredOrder = 0;
4297 updatePreferredIndicesLP();
4298 mSettings.writeLP();
4299 }
4300 }
4301 }
4302 }
4303
4304 private void updatePreferredIndicesLP() {
4305 final ArrayList<PackageSetting> pkgs
4306 = mSettings.mPreferredPackages;
4307 final int N = pkgs.size();
4308 for (int i=0; i<N; i++) {
4309 pkgs.get(i).pkg.mPreferredOrder = N - i;
4310 }
4311 }
4312
4313 public List<PackageInfo> getPreferredPackages(int flags) {
4314 synchronized (mPackages) {
4315 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4316 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4317 final int N = pref.size();
4318 for (int i=0; i<N; i++) {
4319 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4320 }
4321 return res;
4322 }
4323 }
4324
4325 public void addPreferredActivity(IntentFilter filter, int match,
4326 ComponentName[] set, ComponentName activity) {
4327 mContext.enforceCallingOrSelfPermission(
4328 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4329
4330 synchronized (mPackages) {
4331 Log.i(TAG, "Adding preferred activity " + activity + ":");
4332 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4333 mSettings.mPreferredActivities.addFilter(
4334 new PreferredActivity(filter, match, set, activity));
4335 mSettings.writeLP();
4336 }
4337 }
4338
4339 public void clearPackagePreferredActivities(String packageName) {
4340 mContext.enforceCallingOrSelfPermission(
4341 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4342
4343 synchronized (mPackages) {
4344 if (clearPackagePreferredActivitiesLP(packageName)) {
4345 mSettings.writeLP();
4346 }
4347 }
4348 }
4349
4350 boolean clearPackagePreferredActivitiesLP(String packageName) {
4351 boolean changed = false;
4352 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4353 while (it.hasNext()) {
4354 PreferredActivity pa = it.next();
4355 if (pa.mActivity.getPackageName().equals(packageName)) {
4356 it.remove();
4357 changed = true;
4358 }
4359 }
4360 return changed;
4361 }
4362
4363 public int getPreferredActivities(List<IntentFilter> outFilters,
4364 List<ComponentName> outActivities, String packageName) {
4365
4366 int num = 0;
4367 synchronized (mPackages) {
4368 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4369 while (it.hasNext()) {
4370 PreferredActivity pa = it.next();
4371 if (packageName == null
4372 || pa.mActivity.getPackageName().equals(packageName)) {
4373 if (outFilters != null) {
4374 outFilters.add(new IntentFilter(pa));
4375 }
4376 if (outActivities != null) {
4377 outActivities.add(pa.mActivity);
4378 }
4379 }
4380 }
4381 }
4382
4383 return num;
4384 }
4385
4386 public void setApplicationEnabledSetting(String appPackageName,
4387 int newState, int flags) {
4388 setEnabledSetting(appPackageName, null, newState, flags);
4389 }
4390
4391 public void setComponentEnabledSetting(ComponentName componentName,
4392 int newState, int flags) {
4393 setEnabledSetting(componentName.getPackageName(),
4394 componentName.getClassName(), newState, flags);
4395 }
4396
4397 private void setEnabledSetting(
4398 final String packageNameStr, String classNameStr, int newState, final int flags) {
4399 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4400 || newState == COMPONENT_ENABLED_STATE_ENABLED
4401 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4402 throw new IllegalArgumentException("Invalid new component state: "
4403 + newState);
4404 }
4405 PackageSetting pkgSetting;
4406 final int uid = Binder.getCallingUid();
4407 final int permission = mContext.checkCallingPermission(
4408 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4409 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4410 int packageUid = -1;
4411 synchronized (mPackages) {
4412 pkgSetting = mSettings.mPackages.get(packageNameStr);
4413 if (pkgSetting == null) {
4414 if (classNameStr == null) {
4415 throw new IllegalArgumentException(
4416 "Unknown package: " + packageNameStr);
4417 }
4418 throw new IllegalArgumentException(
4419 "Unknown component: " + packageNameStr
4420 + "/" + classNameStr);
4421 }
4422 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4423 throw new SecurityException(
4424 "Permission Denial: attempt to change component state from pid="
4425 + Binder.getCallingPid()
4426 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4427 }
4428 packageUid = pkgSetting.userId;
4429 if (classNameStr == null) {
4430 // We're dealing with an application/package level state change
4431 pkgSetting.enabled = newState;
4432 } else {
4433 // We're dealing with a component level state change
4434 switch (newState) {
4435 case COMPONENT_ENABLED_STATE_ENABLED:
4436 pkgSetting.enableComponentLP(classNameStr);
4437 break;
4438 case COMPONENT_ENABLED_STATE_DISABLED:
4439 pkgSetting.disableComponentLP(classNameStr);
4440 break;
4441 case COMPONENT_ENABLED_STATE_DEFAULT:
4442 pkgSetting.restoreComponentLP(classNameStr);
4443 break;
4444 default:
4445 Log.e(TAG, "Invalid new component state: " + newState);
4446 }
4447 }
4448 mSettings.writeLP();
4449 }
4450
4451 long callingId = Binder.clearCallingIdentity();
4452 try {
4453 Bundle extras = new Bundle(2);
4454 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
4455 (flags&PackageManager.DONT_KILL_APP) != 0);
4456 extras.putInt(Intent.EXTRA_UID, packageUid);
4457 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
4458 } finally {
4459 Binder.restoreCallingIdentity(callingId);
4460 }
4461 }
4462
4463 public int getApplicationEnabledSetting(String appPackageName) {
4464 synchronized (mPackages) {
4465 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
4466 if (pkg == null) {
4467 throw new IllegalArgumentException("Unknown package: " + appPackageName);
4468 }
4469 return pkg.enabled;
4470 }
4471 }
4472
4473 public int getComponentEnabledSetting(ComponentName componentName) {
4474 synchronized (mPackages) {
4475 final String packageNameStr = componentName.getPackageName();
4476 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
4477 if (pkg == null) {
4478 throw new IllegalArgumentException("Unknown component: " + componentName);
4479 }
4480 final String classNameStr = componentName.getClassName();
4481 return pkg.currentEnabledStateLP(classNameStr);
4482 }
4483 }
4484
4485 public void enterSafeMode() {
4486 if (!mSystemReady) {
4487 mSafeMode = true;
4488 }
4489 }
4490
4491 public void systemReady() {
4492 mSystemReady = true;
4493 }
4494
4495 public boolean isSafeMode() {
4496 return mSafeMode;
4497 }
4498
4499 public boolean hasSystemUidErrors() {
4500 return mHasSystemUidErrors;
4501 }
4502
4503 static String arrayToString(int[] array) {
4504 StringBuffer buf = new StringBuffer(128);
4505 buf.append('[');
4506 if (array != null) {
4507 for (int i=0; i<array.length; i++) {
4508 if (i > 0) buf.append(", ");
4509 buf.append(array[i]);
4510 }
4511 }
4512 buf.append(']');
4513 return buf.toString();
4514 }
4515
4516 @Override
4517 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4518 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4519 != PackageManager.PERMISSION_GRANTED) {
4520 pw.println("Permission Denial: can't dump ActivityManager from from pid="
4521 + Binder.getCallingPid()
4522 + ", uid=" + Binder.getCallingUid()
4523 + " without permission "
4524 + android.Manifest.permission.DUMP);
4525 return;
4526 }
4527
4528 Printer printer = new PrintWriterPrinter(pw);
4529 synchronized (mPackages) {
4530 pw.println("Activity Resolver Table:");
4531 mActivities.dump(printer, " ");
4532 pw.println(" ");
4533 pw.println("Receiver Resolver Table:");
4534 mReceivers.dump(printer, " ");
4535 pw.println(" ");
4536 pw.println("Service Resolver Table:");
4537 mServices.dump(printer, " ");
4538 pw.println(" ");
4539 pw.println("Preferred Activities:");
4540 mSettings.mPreferredActivities.dump(printer, " ");
4541 pw.println(" ");
4542 pw.println("Preferred Packages:");
4543 {
4544 for (PackageSetting ps : mSettings.mPreferredPackages) {
4545 pw.println(" " + ps.name);
4546 }
4547 }
4548 pw.println(" ");
4549 pw.println("Permissions:");
4550 {
4551 for (BasePermission p : mSettings.mPermissions.values()) {
4552 pw.println(" Permission [" + p.name + "] ("
4553 + Integer.toHexString(System.identityHashCode(p))
4554 + "):");
4555 pw.println(" sourcePackage=" + p.sourcePackage);
4556 pw.println(" uid=" + p.uid
4557 + " gids=" + arrayToString(p.gids)
4558 + " type=" + p.type);
4559 }
4560 }
4561 pw.println(" ");
4562 pw.println("Packages:");
4563 {
4564 for (PackageSetting ps : mSettings.mPackages.values()) {
4565 pw.println(" Package [" + ps.name + "] ("
4566 + Integer.toHexString(System.identityHashCode(ps))
4567 + "):");
4568 pw.println(" userId=" + ps.userId
4569 + " gids=" + arrayToString(ps.gids));
4570 pw.println(" sharedUser=" + ps.sharedUser);
4571 pw.println(" pkg=" + ps.pkg);
4572 pw.println(" codePath=" + ps.codePathString);
4573 pw.println(" resourcePath=" + ps.resourcePathString);
4574 if (ps.pkg != null) {
4575 pw.println(" dataDir=" + ps.pkg.applicationInfo.dataDir);
4576 }
4577 pw.println(" timeStamp=" + ps.getTimeStampStr());
4578 pw.println(" signatures=" + ps.signatures);
4579 pw.println(" permissionsFixed=" + ps.permissionsFixed
4580 + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags)
4581 + " installStatus=" + ps.installStatus
4582 + " enabled=" + ps.enabled);
4583 if (ps.disabledComponents.size() > 0) {
4584 pw.println(" disabledComponents:");
4585 for (String s : ps.disabledComponents) {
4586 pw.println(" " + s);
4587 }
4588 }
4589 if (ps.enabledComponents.size() > 0) {
4590 pw.println(" enabledComponents:");
4591 for (String s : ps.enabledComponents) {
4592 pw.println(" " + s);
4593 }
4594 }
4595 pw.println(" grantedPermissions:");
4596 for (String s : ps.grantedPermissions) {
4597 pw.println(" " + s);
4598 }
4599 pw.println(" loadedPermissions:");
4600 for (String s : ps.loadedPermissions) {
4601 pw.println(" " + s);
4602 }
4603 }
4604 }
4605 pw.println(" ");
4606 pw.println("Shared Users:");
4607 {
4608 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
4609 pw.println(" SharedUser [" + su.name + "] ("
4610 + Integer.toHexString(System.identityHashCode(su))
4611 + "):");
4612 pw.println(" userId=" + su.userId
4613 + " gids=" + arrayToString(su.gids));
4614 pw.println(" grantedPermissions:");
4615 for (String s : su.grantedPermissions) {
4616 pw.println(" " + s);
4617 }
4618 pw.println(" loadedPermissions:");
4619 for (String s : su.loadedPermissions) {
4620 pw.println(" " + s);
4621 }
4622 }
4623 }
4624 pw.println(" ");
4625 pw.println("Settings parse messages:");
4626 pw.println(mSettings.mReadMessages.toString());
4627 }
4628 }
4629
4630 static final class BasePermission {
4631 final static int TYPE_NORMAL = 0;
4632 final static int TYPE_BUILTIN = 1;
4633 final static int TYPE_DYNAMIC = 2;
4634
4635 final String name;
4636 final String sourcePackage;
4637 final int type;
4638 PackageParser.Permission perm;
4639 PermissionInfo pendingInfo;
4640 int uid;
4641 int[] gids;
4642
4643 BasePermission(String _name, String _sourcePackage, int _type) {
4644 name = _name;
4645 sourcePackage = _sourcePackage;
4646 type = _type;
4647 }
4648 }
4649
4650 static class PackageSignatures {
4651 private Signature[] mSignatures;
4652
4653 PackageSignatures(Signature[] sigs) {
4654 assignSignatures(sigs);
4655 }
4656
4657 PackageSignatures() {
4658 }
4659
4660 void writeXml(XmlSerializer serializer, String tagName,
4661 ArrayList<Signature> pastSignatures) throws IOException {
4662 if (mSignatures == null) {
4663 return;
4664 }
4665 serializer.startTag(null, tagName);
4666 serializer.attribute(null, "count",
4667 Integer.toString(mSignatures.length));
4668 for (int i=0; i<mSignatures.length; i++) {
4669 serializer.startTag(null, "cert");
4670 final Signature sig = mSignatures[i];
4671 final int sigHash = sig.hashCode();
4672 final int numPast = pastSignatures.size();
4673 int j;
4674 for (j=0; j<numPast; j++) {
4675 Signature pastSig = pastSignatures.get(j);
4676 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
4677 serializer.attribute(null, "index", Integer.toString(j));
4678 break;
4679 }
4680 }
4681 if (j >= numPast) {
4682 pastSignatures.add(sig);
4683 serializer.attribute(null, "index", Integer.toString(numPast));
4684 serializer.attribute(null, "key", sig.toCharsString());
4685 }
4686 serializer.endTag(null, "cert");
4687 }
4688 serializer.endTag(null, tagName);
4689 }
4690
4691 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
4692 throws IOException, XmlPullParserException {
4693 String countStr = parser.getAttributeValue(null, "count");
4694 if (countStr == null) {
4695 reportSettingsProblem(Log.WARN,
4696 "Error in package manager settings: <signatures> has"
4697 + " no count at " + parser.getPositionDescription());
4698 XmlUtils.skipCurrentTag(parser);
4699 }
4700 final int count = Integer.parseInt(countStr);
4701 mSignatures = new Signature[count];
4702 int pos = 0;
4703
4704 int outerDepth = parser.getDepth();
4705 int type;
4706 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4707 && (type != XmlPullParser.END_TAG
4708 || parser.getDepth() > outerDepth)) {
4709 if (type == XmlPullParser.END_TAG
4710 || type == XmlPullParser.TEXT) {
4711 continue;
4712 }
4713
4714 String tagName = parser.getName();
4715 if (tagName.equals("cert")) {
4716 if (pos < count) {
4717 String index = parser.getAttributeValue(null, "index");
4718 if (index != null) {
4719 try {
4720 int idx = Integer.parseInt(index);
4721 String key = parser.getAttributeValue(null, "key");
4722 if (key == null) {
4723 if (idx >= 0 && idx < pastSignatures.size()) {
4724 Signature sig = pastSignatures.get(idx);
4725 if (sig != null) {
4726 mSignatures[pos] = pastSignatures.get(idx);
4727 pos++;
4728 } else {
4729 reportSettingsProblem(Log.WARN,
4730 "Error in package manager settings: <cert> "
4731 + "index " + index + " is not defined at "
4732 + parser.getPositionDescription());
4733 }
4734 } else {
4735 reportSettingsProblem(Log.WARN,
4736 "Error in package manager settings: <cert> "
4737 + "index " + index + " is out of bounds at "
4738 + parser.getPositionDescription());
4739 }
4740 } else {
4741 while (pastSignatures.size() <= idx) {
4742 pastSignatures.add(null);
4743 }
4744 Signature sig = new Signature(key);
4745 pastSignatures.set(idx, sig);
4746 mSignatures[pos] = sig;
4747 pos++;
4748 }
4749 } catch (NumberFormatException e) {
4750 reportSettingsProblem(Log.WARN,
4751 "Error in package manager settings: <cert> "
4752 + "index " + index + " is not a number at "
4753 + parser.getPositionDescription());
4754 }
4755 } else {
4756 reportSettingsProblem(Log.WARN,
4757 "Error in package manager settings: <cert> has"
4758 + " no index at " + parser.getPositionDescription());
4759 }
4760 } else {
4761 reportSettingsProblem(Log.WARN,
4762 "Error in package manager settings: too "
4763 + "many <cert> tags, expected " + count
4764 + " at " + parser.getPositionDescription());
4765 }
4766 } else {
4767 reportSettingsProblem(Log.WARN,
4768 "Unknown element under <cert>: "
4769 + parser.getName());
4770 }
4771 XmlUtils.skipCurrentTag(parser);
4772 }
4773
4774 if (pos < count) {
4775 // Should never happen -- there is an error in the written
4776 // settings -- but if it does we don't want to generate
4777 // a bad array.
4778 Signature[] newSigs = new Signature[pos];
4779 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
4780 mSignatures = newSigs;
4781 }
4782 }
4783
4784 /**
4785 * If any of the given 'sigs' is contained in the existing signatures,
4786 * then completely replace the current signatures with the ones in
4787 * 'sigs'. This is used for updating an existing package to a newly
4788 * installed version.
4789 */
4790 boolean updateSignatures(Signature[] sigs, boolean update) {
4791 if (mSignatures == null) {
4792 if (update) {
4793 assignSignatures(sigs);
4794 }
4795 return true;
4796 }
4797 if (sigs == null) {
4798 return false;
4799 }
4800
4801 for (int i=0; i<sigs.length; i++) {
4802 Signature sig = sigs[i];
4803 for (int j=0; j<mSignatures.length; j++) {
4804 if (mSignatures[j].equals(sig)) {
4805 if (update) {
4806 assignSignatures(sigs);
4807 }
4808 return true;
4809 }
4810 }
4811 }
4812 return false;
4813 }
4814
4815 /**
4816 * If any of the given 'sigs' is contained in the existing signatures,
4817 * then add in any new signatures found in 'sigs'. This is used for
4818 * including a new package into an existing shared user id.
4819 */
4820 boolean mergeSignatures(Signature[] sigs, boolean update) {
4821 if (mSignatures == null) {
4822 if (update) {
4823 assignSignatures(sigs);
4824 }
4825 return true;
4826 }
4827 if (sigs == null) {
4828 return false;
4829 }
4830
4831 Signature[] added = null;
4832 int addedCount = 0;
4833 boolean haveMatch = false;
4834 for (int i=0; i<sigs.length; i++) {
4835 Signature sig = sigs[i];
4836 boolean found = false;
4837 for (int j=0; j<mSignatures.length; j++) {
4838 if (mSignatures[j].equals(sig)) {
4839 found = true;
4840 haveMatch = true;
4841 break;
4842 }
4843 }
4844
4845 if (!found) {
4846 if (added == null) {
4847 added = new Signature[sigs.length];
4848 }
4849 added[i] = sig;
4850 addedCount++;
4851 }
4852 }
4853
4854 if (!haveMatch) {
4855 // Nothing matched -- reject the new signatures.
4856 return false;
4857 }
4858 if (added == null) {
4859 // Completely matched -- nothing else to do.
4860 return true;
4861 }
4862
4863 // Add additional signatures in.
4864 if (update) {
4865 Signature[] total = new Signature[addedCount+mSignatures.length];
4866 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
4867 int j = mSignatures.length;
4868 for (int i=0; i<added.length; i++) {
4869 if (added[i] != null) {
4870 total[j] = added[i];
4871 j++;
4872 }
4873 }
4874 mSignatures = total;
4875 }
4876 return true;
4877 }
4878
4879 private void assignSignatures(Signature[] sigs) {
4880 if (sigs == null) {
4881 mSignatures = null;
4882 return;
4883 }
4884 mSignatures = new Signature[sigs.length];
4885 for (int i=0; i<sigs.length; i++) {
4886 mSignatures[i] = sigs[i];
4887 }
4888 }
4889
4890 @Override
4891 public String toString() {
4892 StringBuffer buf = new StringBuffer(128);
4893 buf.append("PackageSignatures{");
4894 buf.append(Integer.toHexString(System.identityHashCode(this)));
4895 buf.append(" [");
4896 if (mSignatures != null) {
4897 for (int i=0; i<mSignatures.length; i++) {
4898 if (i > 0) buf.append(", ");
4899 buf.append(Integer.toHexString(
4900 System.identityHashCode(mSignatures[i])));
4901 }
4902 }
4903 buf.append("]}");
4904 return buf.toString();
4905 }
4906 }
4907
4908 static class PreferredActivity extends IntentFilter {
4909 final int mMatch;
4910 final String[] mSetPackages;
4911 final String[] mSetClasses;
4912 final String[] mSetComponents;
4913 final ComponentName mActivity;
4914 final String mShortActivity;
4915 String mParseError;
4916
4917 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
4918 ComponentName activity) {
4919 super(filter);
4920 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
4921 mActivity = activity;
4922 mShortActivity = activity.flattenToShortString();
4923 mParseError = null;
4924 if (set != null) {
4925 final int N = set.length;
4926 String[] myPackages = new String[N];
4927 String[] myClasses = new String[N];
4928 String[] myComponents = new String[N];
4929 for (int i=0; i<N; i++) {
4930 ComponentName cn = set[i];
4931 if (cn == null) {
4932 mSetPackages = null;
4933 mSetClasses = null;
4934 mSetComponents = null;
4935 return;
4936 }
4937 myPackages[i] = cn.getPackageName().intern();
4938 myClasses[i] = cn.getClassName().intern();
4939 myComponents[i] = cn.flattenToShortString().intern();
4940 }
4941 mSetPackages = myPackages;
4942 mSetClasses = myClasses;
4943 mSetComponents = myComponents;
4944 } else {
4945 mSetPackages = null;
4946 mSetClasses = null;
4947 mSetComponents = null;
4948 }
4949 }
4950
4951 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
4952 IOException {
4953 mShortActivity = parser.getAttributeValue(null, "name");
4954 mActivity = ComponentName.unflattenFromString(mShortActivity);
4955 if (mActivity == null) {
4956 mParseError = "Bad activity name " + mShortActivity;
4957 }
4958 String matchStr = parser.getAttributeValue(null, "match");
4959 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
4960 String setCountStr = parser.getAttributeValue(null, "set");
4961 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
4962
4963 String[] myPackages = setCount > 0 ? new String[setCount] : null;
4964 String[] myClasses = setCount > 0 ? new String[setCount] : null;
4965 String[] myComponents = setCount > 0 ? new String[setCount] : null;
4966
4967 int setPos = 0;
4968
4969 int outerDepth = parser.getDepth();
4970 int type;
4971 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4972 && (type != XmlPullParser.END_TAG
4973 || parser.getDepth() > outerDepth)) {
4974 if (type == XmlPullParser.END_TAG
4975 || type == XmlPullParser.TEXT) {
4976 continue;
4977 }
4978
4979 String tagName = parser.getName();
4980 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
4981 // + parser.getDepth() + " tag=" + tagName);
4982 if (tagName.equals("set")) {
4983 String name = parser.getAttributeValue(null, "name");
4984 if (name == null) {
4985 if (mParseError == null) {
4986 mParseError = "No name in set tag in preferred activity "
4987 + mShortActivity;
4988 }
4989 } else if (setPos >= setCount) {
4990 if (mParseError == null) {
4991 mParseError = "Too many set tags in preferred activity "
4992 + mShortActivity;
4993 }
4994 } else {
4995 ComponentName cn = ComponentName.unflattenFromString(name);
4996 if (cn == null) {
4997 if (mParseError == null) {
4998 mParseError = "Bad set name " + name + " in preferred activity "
4999 + mShortActivity;
5000 }
5001 } else {
5002 myPackages[setPos] = cn.getPackageName();
5003 myClasses[setPos] = cn.getClassName();
5004 myComponents[setPos] = name;
5005 setPos++;
5006 }
5007 }
5008 XmlUtils.skipCurrentTag(parser);
5009 } else if (tagName.equals("filter")) {
5010 //Log.i(TAG, "Starting to parse filter...");
5011 readFromXml(parser);
5012 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5013 // + parser.getDepth() + " tag=" + parser.getName());
5014 } else {
5015 reportSettingsProblem(Log.WARN,
5016 "Unknown element under <preferred-activities>: "
5017 + parser.getName());
5018 XmlUtils.skipCurrentTag(parser);
5019 }
5020 }
5021
5022 if (setPos != setCount) {
5023 if (mParseError == null) {
5024 mParseError = "Not enough set tags (expected " + setCount
5025 + " but found " + setPos + ") in " + mShortActivity;
5026 }
5027 }
5028
5029 mSetPackages = myPackages;
5030 mSetClasses = myClasses;
5031 mSetComponents = myComponents;
5032 }
5033
5034 public void writeToXml(XmlSerializer serializer) throws IOException {
5035 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5036 serializer.attribute(null, "name", mShortActivity);
5037 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5038 serializer.attribute(null, "set", Integer.toString(NS));
5039 for (int s=0; s<NS; s++) {
5040 serializer.startTag(null, "set");
5041 serializer.attribute(null, "name", mSetComponents[s]);
5042 serializer.endTag(null, "set");
5043 }
5044 serializer.startTag(null, "filter");
5045 super.writeToXml(serializer);
5046 serializer.endTag(null, "filter");
5047 }
5048
5049 boolean sameSet(List<ResolveInfo> query, int priority) {
5050 if (mSetPackages == null) return false;
5051 final int NQ = query.size();
5052 final int NS = mSetPackages.length;
5053 int numMatch = 0;
5054 for (int i=0; i<NQ; i++) {
5055 ResolveInfo ri = query.get(i);
5056 if (ri.priority != priority) continue;
5057 ActivityInfo ai = ri.activityInfo;
5058 boolean good = false;
5059 for (int j=0; j<NS; j++) {
5060 if (mSetPackages[j].equals(ai.packageName)
5061 && mSetClasses[j].equals(ai.name)) {
5062 numMatch++;
5063 good = true;
5064 break;
5065 }
5066 }
5067 if (!good) return false;
5068 }
5069 return numMatch == NS;
5070 }
5071 }
5072
5073 static class GrantedPermissions {
5074 final int pkgFlags;
5075
5076 HashSet<String> grantedPermissions = new HashSet<String>();
5077 int[] gids;
5078
5079 HashSet<String> loadedPermissions = new HashSet<String>();
5080
5081 GrantedPermissions(int pkgFlags) {
5082 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5083 }
5084 }
5085
5086 /**
5087 * Settings base class for pending and resolved classes.
5088 */
5089 static class PackageSettingBase extends GrantedPermissions {
5090 final String name;
5091 final File codePath;
5092 final String codePathString;
5093 final File resourcePath;
5094 final String resourcePathString;
5095 private long timeStamp;
5096 private String timeStampString = "0";
5097
5098 PackageSignatures signatures = new PackageSignatures();
5099
5100 boolean permissionsFixed;
5101
5102 /* Explicitly disabled components */
5103 HashSet<String> disabledComponents = new HashSet<String>(0);
5104 /* Explicitly enabled components */
5105 HashSet<String> enabledComponents = new HashSet<String>(0);
5106 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5107 int installStatus = PKG_INSTALL_COMPLETE;
5108
5109 PackageSettingBase(String name, File codePath, File resourcePath,
5110 int pkgFlags) {
5111 super(pkgFlags);
5112 this.name = name;
5113 this.codePath = codePath;
5114 this.codePathString = codePath.toString();
5115 this.resourcePath = resourcePath;
5116 this.resourcePathString = resourcePath.toString();
5117 }
5118
5119 public void setInstallStatus(int newStatus) {
5120 installStatus = newStatus;
5121 }
5122
5123 public int getInstallStatus() {
5124 return installStatus;
5125 }
5126
5127 public void setTimeStamp(long newStamp) {
5128 if (newStamp != timeStamp) {
5129 timeStamp = newStamp;
5130 timeStampString = Long.toString(newStamp);
5131 }
5132 }
5133
5134 public void setTimeStamp(long newStamp, String newStampStr) {
5135 timeStamp = newStamp;
5136 timeStampString = newStampStr;
5137 }
5138
5139 public long getTimeStamp() {
5140 return timeStamp;
5141 }
5142
5143 public String getTimeStampStr() {
5144 return timeStampString;
5145 }
5146
5147 public void copyFrom(PackageSettingBase base) {
5148 grantedPermissions = base.grantedPermissions;
5149 gids = base.gids;
5150 loadedPermissions = base.loadedPermissions;
5151
5152 timeStamp = base.timeStamp;
5153 timeStampString = base.timeStampString;
5154 signatures = base.signatures;
5155 permissionsFixed = base.permissionsFixed;
5156 disabledComponents = base.disabledComponents;
5157 enabledComponents = base.enabledComponents;
5158 enabled = base.enabled;
5159 installStatus = base.installStatus;
5160 }
5161
5162 void enableComponentLP(String componentClassName) {
5163 disabledComponents.remove(componentClassName);
5164 enabledComponents.add(componentClassName);
5165 }
5166
5167 void disableComponentLP(String componentClassName) {
5168 enabledComponents.remove(componentClassName);
5169 disabledComponents.add(componentClassName);
5170 }
5171
5172 void restoreComponentLP(String componentClassName) {
5173 enabledComponents.remove(componentClassName);
5174 disabledComponents.remove(componentClassName);
5175 }
5176
5177 int currentEnabledStateLP(String componentName) {
5178 if (enabledComponents.contains(componentName)) {
5179 return COMPONENT_ENABLED_STATE_ENABLED;
5180 } else if (disabledComponents.contains(componentName)) {
5181 return COMPONENT_ENABLED_STATE_DISABLED;
5182 } else {
5183 return COMPONENT_ENABLED_STATE_DEFAULT;
5184 }
5185 }
5186 }
5187
5188 /**
5189 * Settings data for a particular package we know about.
5190 */
5191 static final class PackageSetting extends PackageSettingBase {
5192 int userId;
5193 PackageParser.Package pkg;
5194 SharedUserSetting sharedUser;
5195
5196 PackageSetting(String name, File codePath, File resourcePath,
5197 int pkgFlags) {
5198 super(name, codePath, resourcePath, pkgFlags);
5199 }
5200
5201 @Override
5202 public String toString() {
5203 return "PackageSetting{"
5204 + Integer.toHexString(System.identityHashCode(this))
5205 + " " + name + "/" + userId + "}";
5206 }
5207 }
5208
5209 /**
5210 * Settings data for a particular shared user ID we know about.
5211 */
5212 static final class SharedUserSetting extends GrantedPermissions {
5213 final String name;
5214 int userId;
5215 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5216 final PackageSignatures signatures = new PackageSignatures();
5217
5218 SharedUserSetting(String _name, int _pkgFlags) {
5219 super(_pkgFlags);
5220 name = _name;
5221 }
5222
5223 @Override
5224 public String toString() {
5225 return "SharedUserSetting{"
5226 + Integer.toHexString(System.identityHashCode(this))
5227 + " " + name + "/" + userId + "}";
5228 }
5229 }
5230
5231 /**
5232 * Holds information about dynamic settings.
5233 */
5234 private static final class Settings {
5235 private final File mSettingsFilename;
5236 private final File mBackupSettingsFilename;
5237 private final HashMap<String, PackageSetting> mPackages =
5238 new HashMap<String, PackageSetting>();
5239 // The user's preferred packages/applications, in order of preference.
5240 // First is the most preferred.
5241 private final ArrayList<PackageSetting> mPreferredPackages =
5242 new ArrayList<PackageSetting>();
5243 // List of replaced system applications
5244 final HashMap<String, PackageSetting> mDisabledSysPackages =
5245 new HashMap<String, PackageSetting>();
5246
5247 // The user's preferred activities associated with particular intent
5248 // filters.
5249 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5250 new IntentResolver<PreferredActivity, PreferredActivity>() {
5251 @Override
5252 protected void dumpFilter(Printer out, String prefix,
5253 PreferredActivity filter) {
5254 out.println(prefix
5255 + Integer.toHexString(System.identityHashCode(filter))
5256 + " " + filter.mActivity.flattenToShortString()
5257 + " match=0x" + Integer.toHexString(filter.mMatch));
5258 if (filter.mSetComponents != null) {
5259 out.println(prefix + " Selected from:");
5260 for (int i=0; i<filter.mSetComponents.length; i++) {
5261 out.println(prefix + " " + filter.mSetComponents[i]);
5262 }
5263 }
5264 }
5265 };
5266 private final HashMap<String, SharedUserSetting> mSharedUsers =
5267 new HashMap<String, SharedUserSetting>();
5268 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5269 private final SparseArray<Object> mOtherUserIds =
5270 new SparseArray<Object>();
5271
5272 // For reading/writing settings file.
5273 private final ArrayList<Signature> mPastSignatures =
5274 new ArrayList<Signature>();
5275
5276 // Mapping from permission names to info about them.
5277 final HashMap<String, BasePermission> mPermissions =
5278 new HashMap<String, BasePermission>();
5279
5280 // Mapping from permission tree names to info about them.
5281 final HashMap<String, BasePermission> mPermissionTrees =
5282 new HashMap<String, BasePermission>();
5283
5284 private final ArrayList<String> mPendingPreferredPackages
5285 = new ArrayList<String>();
5286
5287 private final StringBuilder mReadMessages = new StringBuilder();
5288
5289 private static final class PendingPackage extends PackageSettingBase {
5290 final int sharedId;
5291
5292 PendingPackage(String name, File codePath, File resourcePath,
5293 int sharedId, int pkgFlags) {
5294 super(name, codePath, resourcePath, pkgFlags);
5295 this.sharedId = sharedId;
5296 }
5297 }
5298 private final ArrayList<PendingPackage> mPendingPackages
5299 = new ArrayList<PendingPackage>();
5300
5301 Settings() {
5302 File dataDir = Environment.getDataDirectory();
5303 File systemDir = new File(dataDir, "system");
5304 systemDir.mkdirs();
5305 FileUtils.setPermissions(systemDir.toString(),
5306 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5307 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5308 -1, -1);
5309 mSettingsFilename = new File(systemDir, "packages.xml");
5310 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5311 }
5312
5313 PackageSetting getPackageLP(PackageParser.Package pkg,
5314 SharedUserSetting sharedUser, File codePath, File resourcePath,
5315 int pkgFlags, boolean create, boolean add) {
5316 final String name = pkg.packageName;
5317 PackageSetting p = getPackageLP(name, sharedUser, codePath,
5318 resourcePath, pkgFlags, create, add);
5319
5320 if (p != null) {
5321 p.pkg = pkg;
5322 }
5323 return p;
5324 }
5325
5326 PackageSetting peekPackageLP(String name, String codePath) {
5327 PackageSetting p = mPackages.get(name);
5328 if (p != null && p.codePath.getPath().equals(codePath)) {
5329 return p;
5330 }
5331 return null;
5332 }
5333
5334 void setInstallStatus(String pkgName, int status) {
5335 PackageSetting p = mPackages.get(pkgName);
5336 if(p != null) {
5337 if(p.getInstallStatus() != status) {
5338 p.setInstallStatus(status);
5339 }
5340 }
5341 }
5342
5343 int getInstallStatus(String pkgName) {
5344 PackageSetting p = mPackages.get(pkgName);
5345 if(p != null) {
5346 return p.getInstallStatus();
5347 }
5348 return -1;
5349 }
5350
5351 SharedUserSetting getSharedUserLP(String name,
5352 int pkgFlags, boolean create) {
5353 SharedUserSetting s = mSharedUsers.get(name);
5354 if (s == null) {
5355 if (!create) {
5356 return null;
5357 }
5358 s = new SharedUserSetting(name, pkgFlags);
5359 if (MULTIPLE_APPLICATION_UIDS) {
5360 s.userId = newUserIdLP(s);
5361 } else {
5362 s.userId = FIRST_APPLICATION_UID;
5363 }
5364 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
5365 // < 0 means we couldn't assign a userid; fall out and return
5366 // s, which is currently null
5367 if (s.userId >= 0) {
5368 mSharedUsers.put(name, s);
5369 }
5370 }
5371
5372 return s;
5373 }
5374
5375 int disableSystemPackageLP(String name) {
5376 PackageSetting p = mPackages.get(name);
5377 if(p == null) {
5378 Log.w(TAG, "Package:"+name+" is not an installed package");
5379 return -1;
5380 }
5381 PackageSetting dp = mDisabledSysPackages.get(name);
5382 // always make sure the system package code and resource paths dont change
5383 if(dp == null) {
5384 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5385 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5386 }
5387 mDisabledSysPackages.put(name, p);
5388 }
5389 return removePackageLP(name);
5390 }
5391
5392 PackageSetting enableSystemPackageLP(String name) {
5393 PackageSetting p = mDisabledSysPackages.get(name);
5394 if(p == null) {
5395 Log.w(TAG, "Package:"+name+" is not disabled");
5396 return null;
5397 }
5398 // Reset flag in ApplicationInfo object
5399 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5400 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5401 }
5402 PackageSetting ret = addPackageLP(name, p.codePath,
5403 p.resourcePath, p.userId, p.pkgFlags);
5404 mDisabledSysPackages.remove(name);
5405 return ret;
5406 }
5407
5408 PackageSetting addPackageLP(String name, File codePath,
5409 File resourcePath, int uid, int pkgFlags) {
5410 PackageSetting p = mPackages.get(name);
5411 if (p != null) {
5412 if (p.userId == uid) {
5413 return p;
5414 }
5415 reportSettingsProblem(Log.ERROR,
5416 "Adding duplicate package, keeping first: " + name);
5417 return null;
5418 }
5419 p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
5420 p.userId = uid;
5421 if (addUserIdLP(uid, p, name)) {
5422 mPackages.put(name, p);
5423 return p;
5424 }
5425 return null;
5426 }
5427
5428 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
5429 SharedUserSetting s = mSharedUsers.get(name);
5430 if (s != null) {
5431 if (s.userId == uid) {
5432 return s;
5433 }
5434 reportSettingsProblem(Log.ERROR,
5435 "Adding duplicate shared user, keeping first: " + name);
5436 return null;
5437 }
5438 s = new SharedUserSetting(name, pkgFlags);
5439 s.userId = uid;
5440 if (addUserIdLP(uid, s, name)) {
5441 mSharedUsers.put(name, s);
5442 return s;
5443 }
5444 return null;
5445 }
5446
5447 private PackageSetting getPackageLP(String name,
5448 SharedUserSetting sharedUser, File codePath, File resourcePath,
5449 int pkgFlags, boolean create, boolean add) {
5450 PackageSetting p = mPackages.get(name);
5451 if (p != null) {
5452 if (!p.codePath.equals(codePath)) {
5453 // Check to see if its a disabled system app
5454 PackageSetting ps = mDisabledSysPackages.get(name);
5455 if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
5456 // Could be a replaced system package
5457 // Note that if the user replaced a system app, the user has to physically
5458 // delete the new one in order to revert to the system app. So even
5459 // if the user updated the system app via an update, the user still
5460 // has to delete the one installed in the data partition in order to pick up the
5461 // new system package.
5462 return p;
5463 } else {
5464 reportSettingsProblem(Log.WARN,
5465 "Package " + name + " codePath changed from " + p.codePath
5466 + " to " + codePath + "; replacing with new");
5467 p = null;
5468 }
5469 } else if (p.sharedUser != sharedUser) {
5470 reportSettingsProblem(Log.WARN,
5471 "Package " + name + " shared user changed from "
5472 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
5473 + " to "
5474 + (sharedUser != null ? sharedUser.name : "<nothing>")
5475 + "; replacing with new");
5476 p = null;
5477 }
5478 }
5479 if (p == null) {
5480 // Create a new PackageSettings entry. this can end up here because
5481 // of code path mismatch or user id mismatch of an updated system partition
5482 if (!create) {
5483 return null;
5484 }
5485 p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
5486 p.setTimeStamp(codePath.lastModified());
5487 if (sharedUser != null) {
5488 p.userId = sharedUser.userId;
5489 } else if (MULTIPLE_APPLICATION_UIDS) {
5490 p.userId = newUserIdLP(p);
5491 } else {
5492 p.userId = FIRST_APPLICATION_UID;
5493 }
5494 if (p.userId < 0) {
5495 reportSettingsProblem(Log.WARN,
5496 "Package " + name + " could not be assigned a valid uid");
5497 return null;
5498 }
5499 if (add) {
5500 // Finish adding new package by adding it and updating shared
5501 // user preferences
5502 insertPackageSettingLP(p, name, sharedUser);
5503 }
5504 }
5505 return p;
5506 }
5507
5508 // Utility method that adds a PackageSetting to mPackages and
5509 // completes updating the shared user attributes
5510 private void insertPackageSettingLP(PackageSetting p, String name,
5511 SharedUserSetting sharedUser) {
5512 mPackages.put(name, p);
5513 if (sharedUser != null) {
5514 if (p.sharedUser != null && p.sharedUser != sharedUser) {
5515 reportSettingsProblem(Log.ERROR,
5516 "Package " + p.name + " was user "
5517 + p.sharedUser + " but is now " + sharedUser
5518 + "; I am not changing its files so it will probably fail!");
5519 p.sharedUser.packages.remove(p);
5520 } else if (p.userId != sharedUser.userId) {
5521 reportSettingsProblem(Log.ERROR,
5522 "Package " + p.name + " was user id " + p.userId
5523 + " but is now user " + sharedUser
5524 + " with id " + sharedUser.userId
5525 + "; I am not changing its files so it will probably fail!");
5526 }
5527
5528 sharedUser.packages.add(p);
5529 p.sharedUser = sharedUser;
5530 p.userId = sharedUser.userId;
5531 }
5532 }
5533
5534 private void updateSharedUserPerms (PackageSetting deletedPs) {
5535 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
5536 Log.i(TAG, "Trying to update info for null package. Just ignoring");
5537 return;
5538 }
5539 // No sharedUserId
5540 if (deletedPs.sharedUser == null) {
5541 return;
5542 }
5543 SharedUserSetting sus = deletedPs.sharedUser;
5544 // Update permissions
5545 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
5546 boolean used = false;
5547 if (!sus.grantedPermissions.contains (eachPerm)) {
5548 continue;
5549 }
5550 for (PackageSetting pkg:sus.packages) {
5551 if (pkg.grantedPermissions.contains (eachPerm)) {
5552 used = true;
5553 break;
5554 }
5555 }
5556 if (!used) {
5557 // can safely delete this permission from list
5558 sus.grantedPermissions.remove(eachPerm);
5559 sus.loadedPermissions.remove(eachPerm);
5560 }
5561 }
5562 // Update gids
5563 int newGids[] = null;
5564 for (PackageSetting pkg:sus.packages) {
5565 newGids = appendInts(newGids, pkg.gids);
5566 }
5567 sus.gids = newGids;
5568 }
5569
5570 private int removePackageLP(String name) {
5571 PackageSetting p = mPackages.get(name);
5572 if (p != null) {
5573 mPackages.remove(name);
5574 if (p.sharedUser != null) {
5575 p.sharedUser.packages.remove(p);
5576 if (p.sharedUser.packages.size() == 0) {
5577 mSharedUsers.remove(p.sharedUser.name);
5578 removeUserIdLP(p.sharedUser.userId);
5579 return p.sharedUser.userId;
5580 }
5581 } else {
5582 removeUserIdLP(p.userId);
5583 return p.userId;
5584 }
5585 }
5586 return -1;
5587 }
5588
5589 private boolean addUserIdLP(int uid, Object obj, Object name) {
5590 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
5591 return false;
5592 }
5593
5594 if (uid >= FIRST_APPLICATION_UID) {
5595 int N = mUserIds.size();
5596 final int index = uid - FIRST_APPLICATION_UID;
5597 while (index >= N) {
5598 mUserIds.add(null);
5599 N++;
5600 }
5601 if (mUserIds.get(index) != null) {
5602 reportSettingsProblem(Log.ERROR,
5603 "Adding duplicate shared id: " + uid
5604 + " name=" + name);
5605 return false;
5606 }
5607 mUserIds.set(index, obj);
5608 } else {
5609 if (mOtherUserIds.get(uid) != null) {
5610 reportSettingsProblem(Log.ERROR,
5611 "Adding duplicate shared id: " + uid
5612 + " name=" + name);
5613 return false;
5614 }
5615 mOtherUserIds.put(uid, obj);
5616 }
5617 return true;
5618 }
5619
5620 public Object getUserIdLP(int uid) {
5621 if (uid >= FIRST_APPLICATION_UID) {
5622 int N = mUserIds.size();
5623 final int index = uid - FIRST_APPLICATION_UID;
5624 return index < N ? mUserIds.get(index) : null;
5625 } else {
5626 return mOtherUserIds.get(uid);
5627 }
5628 }
5629
5630 private void removeUserIdLP(int uid) {
5631 if (uid >= FIRST_APPLICATION_UID) {
5632 int N = mUserIds.size();
5633 final int index = uid - FIRST_APPLICATION_UID;
5634 if (index < N) mUserIds.set(index, null);
5635 } else {
5636 mOtherUserIds.remove(uid);
5637 }
5638 }
5639
5640 void writeLP() {
5641 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
5642
5643 // Keep the old settings around until we know the new ones have
5644 // been successfully written.
5645 if (mSettingsFilename.exists()) {
5646 if (mBackupSettingsFilename.exists()) {
5647 mBackupSettingsFilename.delete();
5648 }
5649 mSettingsFilename.renameTo(mBackupSettingsFilename);
5650 }
5651
5652 mPastSignatures.clear();
5653
5654 try {
5655 FileOutputStream str = new FileOutputStream(mSettingsFilename);
5656
5657 //XmlSerializer serializer = XmlUtils.serializerInstance();
5658 XmlSerializer serializer = new FastXmlSerializer();
5659 serializer.setOutput(str, "utf-8");
5660 serializer.startDocument(null, true);
5661 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
5662
5663 serializer.startTag(null, "packages");
5664
5665 serializer.startTag(null, "permission-trees");
5666 for (BasePermission bp : mPermissionTrees.values()) {
5667 writePermission(serializer, bp);
5668 }
5669 serializer.endTag(null, "permission-trees");
5670
5671 serializer.startTag(null, "permissions");
5672 for (BasePermission bp : mPermissions.values()) {
5673 writePermission(serializer, bp);
5674 }
5675 serializer.endTag(null, "permissions");
5676
5677 for (PackageSetting pkg : mPackages.values()) {
5678 writePackage(serializer, pkg);
5679 }
5680
5681 for (PackageSetting pkg : mDisabledSysPackages.values()) {
5682 writeDisabledSysPackage(serializer, pkg);
5683 }
5684
5685 serializer.startTag(null, "preferred-packages");
5686 int N = mPreferredPackages.size();
5687 for (int i=0; i<N; i++) {
5688 PackageSetting pkg = mPreferredPackages.get(i);
5689 serializer.startTag(null, "item");
5690 serializer.attribute(null, "name", pkg.name);
5691 serializer.endTag(null, "item");
5692 }
5693 serializer.endTag(null, "preferred-packages");
5694
5695 serializer.startTag(null, "preferred-activities");
5696 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
5697 serializer.startTag(null, "item");
5698 pa.writeToXml(serializer);
5699 serializer.endTag(null, "item");
5700 }
5701 serializer.endTag(null, "preferred-activities");
5702
5703 for (SharedUserSetting usr : mSharedUsers.values()) {
5704 serializer.startTag(null, "shared-user");
5705 serializer.attribute(null, "name", usr.name);
5706 serializer.attribute(null, "userId",
5707 Integer.toString(usr.userId));
5708 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
5709 serializer.startTag(null, "perms");
5710 for (String name : usr.grantedPermissions) {
5711 serializer.startTag(null, "item");
5712 serializer.attribute(null, "name", name);
5713 serializer.endTag(null, "item");
5714 }
5715 serializer.endTag(null, "perms");
5716 serializer.endTag(null, "shared-user");
5717 }
5718
5719 serializer.endTag(null, "packages");
5720
5721 serializer.endDocument();
5722
5723 str.flush();
5724 str.close();
5725
5726 // New settings successfully written, old ones are no longer
5727 // needed.
5728 mBackupSettingsFilename.delete();
5729 FileUtils.setPermissions(mSettingsFilename.toString(),
5730 FileUtils.S_IRUSR|FileUtils.S_IWUSR
5731 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
5732 |FileUtils.S_IROTH,
5733 -1, -1);
5734
5735 } catch(XmlPullParserException e) {
5736 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5737
5738 } catch(java.io.IOException e) {
5739 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5740
5741 }
5742
5743 //Debug.stopMethodTracing();
5744 }
5745
5746 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
5747 throws java.io.IOException {
5748 serializer.startTag(null, "updated-package");
5749 serializer.attribute(null, "name", pkg.name);
5750 serializer.attribute(null, "codePath", pkg.codePathString);
5751 serializer.attribute(null, "ts", pkg.getTimeStampStr());
5752 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5753 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5754 }
5755 if (pkg.sharedUser == null) {
5756 serializer.attribute(null, "userId",
5757 Integer.toString(pkg.userId));
5758 } else {
5759 serializer.attribute(null, "sharedUserId",
5760 Integer.toString(pkg.userId));
5761 }
5762 serializer.startTag(null, "perms");
5763 if (pkg.sharedUser == null) {
5764 // If this is a shared user, the permissions will
5765 // be written there. We still need to write an
5766 // empty permissions list so permissionsFixed will
5767 // be set.
5768 for (final String name : pkg.grantedPermissions) {
5769 BasePermission bp = mPermissions.get(name);
5770 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
5771 // We only need to write signature or system permissions but this wont
5772 // match the semantics of grantedPermissions. So write all permissions.
5773 serializer.startTag(null, "item");
5774 serializer.attribute(null, "name", name);
5775 serializer.endTag(null, "item");
5776 }
5777 }
5778 }
5779 serializer.endTag(null, "perms");
5780 serializer.endTag(null, "updated-package");
5781 }
5782
5783 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
5784 throws java.io.IOException {
5785 serializer.startTag(null, "package");
5786 serializer.attribute(null, "name", pkg.name);
5787 serializer.attribute(null, "codePath", pkg.codePathString);
5788 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5789 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5790 }
5791 serializer.attribute(null, "system",
5792 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
5793 ? "true" : "false");
5794 serializer.attribute(null, "ts", pkg.getTimeStampStr());
5795 if (pkg.sharedUser == null) {
5796 serializer.attribute(null, "userId",
5797 Integer.toString(pkg.userId));
5798 } else {
5799 serializer.attribute(null, "sharedUserId",
5800 Integer.toString(pkg.userId));
5801 }
5802 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
5803 serializer.attribute(null, "enabled",
5804 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
5805 ? "true" : "false");
5806 }
5807 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
5808 serializer.attribute(null, "installStatus", "false");
5809 }
5810 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
5811 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5812 serializer.startTag(null, "perms");
5813 if (pkg.sharedUser == null) {
5814 // If this is a shared user, the permissions will
5815 // be written there. We still need to write an
5816 // empty permissions list so permissionsFixed will
5817 // be set.
5818 for (final String name : pkg.grantedPermissions) {
5819 serializer.startTag(null, "item");
5820 serializer.attribute(null, "name", name);
5821 serializer.endTag(null, "item");
5822 }
5823 }
5824 serializer.endTag(null, "perms");
5825 }
5826 if (pkg.disabledComponents.size() > 0) {
5827 serializer.startTag(null, "disabled-components");
5828 for (final String name : pkg.disabledComponents) {
5829 serializer.startTag(null, "item");
5830 serializer.attribute(null, "name", name);
5831 serializer.endTag(null, "item");
5832 }
5833 serializer.endTag(null, "disabled-components");
5834 }
5835 if (pkg.enabledComponents.size() > 0) {
5836 serializer.startTag(null, "enabled-components");
5837 for (final String name : pkg.enabledComponents) {
5838 serializer.startTag(null, "item");
5839 serializer.attribute(null, "name", name);
5840 serializer.endTag(null, "item");
5841 }
5842 serializer.endTag(null, "enabled-components");
5843 }
5844 serializer.endTag(null, "package");
5845 }
5846
5847 void writePermission(XmlSerializer serializer, BasePermission bp)
5848 throws XmlPullParserException, java.io.IOException {
5849 if (bp.type != BasePermission.TYPE_BUILTIN
5850 && bp.sourcePackage != null) {
5851 serializer.startTag(null, "item");
5852 serializer.attribute(null, "name", bp.name);
5853 serializer.attribute(null, "package", bp.sourcePackage);
5854 if (DEBUG_SETTINGS) Log.v(TAG,
5855 "Writing perm: name=" + bp.name + " type=" + bp.type);
5856 if (bp.type == BasePermission.TYPE_DYNAMIC) {
5857 PermissionInfo pi = bp.perm != null ? bp.perm.info
5858 : bp.pendingInfo;
5859 if (pi != null) {
5860 serializer.attribute(null, "type", "dynamic");
5861 if (pi.icon != 0) {
5862 serializer.attribute(null, "icon",
5863 Integer.toString(pi.icon));
5864 }
5865 if (pi.nonLocalizedLabel != null) {
5866 serializer.attribute(null, "label",
5867 pi.nonLocalizedLabel.toString());
5868 }
5869 if (pi.protectionLevel !=
5870 PermissionInfo.PROTECTION_NORMAL) {
5871 serializer.attribute(null, "protection",
5872 Integer.toString(pi.protectionLevel));
5873 }
5874 }
5875 }
5876 serializer.endTag(null, "item");
5877 }
5878 }
5879
5880 String getReadMessagesLP() {
5881 return mReadMessages.toString();
5882 }
5883
5884 ArrayList<String> getListOfIncompleteInstallPackages() {
5885 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
5886 Iterator<String> its = kList.iterator();
5887 ArrayList<String> ret = new ArrayList<String>();
5888 while(its.hasNext()) {
5889 String key = its.next();
5890 PackageSetting ps = mPackages.get(key);
5891 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
5892 ret.add(key);
5893 }
5894 }
5895 return ret;
5896 }
5897
5898 boolean readLP() {
5899 FileInputStream str = null;
5900 if (mBackupSettingsFilename.exists()) {
5901 try {
5902 str = new FileInputStream(mBackupSettingsFilename);
5903 mReadMessages.append("Reading from backup settings file\n");
5904 Log.i(TAG, "Reading from backup settings file!");
5905 } catch (java.io.IOException e) {
5906 // We'll try for the normal settings file.
5907 }
5908 }
5909
5910 mPastSignatures.clear();
5911
5912 try {
5913 if (str == null) {
5914 if (!mSettingsFilename.exists()) {
5915 mReadMessages.append("No settings file found\n");
5916 Log.i(TAG, "No current settings file!");
5917 return false;
5918 }
5919 str = new FileInputStream(mSettingsFilename);
5920 }
5921 XmlPullParser parser = Xml.newPullParser();
5922 parser.setInput(str, null);
5923
5924 int type;
5925 while ((type=parser.next()) != XmlPullParser.START_TAG
5926 && type != XmlPullParser.END_DOCUMENT) {
5927 ;
5928 }
5929
5930 if (type != XmlPullParser.START_TAG) {
5931 mReadMessages.append("No start tag found in settings file\n");
5932 Log.e(TAG, "No start tag found in package manager settings");
5933 return false;
5934 }
5935
5936 int outerDepth = parser.getDepth();
5937 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5938 && (type != XmlPullParser.END_TAG
5939 || parser.getDepth() > outerDepth)) {
5940 if (type == XmlPullParser.END_TAG
5941 || type == XmlPullParser.TEXT) {
5942 continue;
5943 }
5944
5945 String tagName = parser.getName();
5946 if (tagName.equals("package")) {
5947 readPackageLP(parser);
5948 } else if (tagName.equals("permissions")) {
5949 readPermissionsLP(mPermissions, parser);
5950 } else if (tagName.equals("permission-trees")) {
5951 readPermissionsLP(mPermissionTrees, parser);
5952 } else if (tagName.equals("shared-user")) {
5953 readSharedUserLP(parser);
5954 } else if (tagName.equals("preferred-packages")) {
5955 readPreferredPackagesLP(parser);
5956 } else if (tagName.equals("preferred-activities")) {
5957 readPreferredActivitiesLP(parser);
5958 } else if(tagName.equals("updated-package")) {
5959 readDisabledSysPackageLP(parser);
5960 } else {
5961 Log.w(TAG, "Unknown element under <packages>: "
5962 + parser.getName());
5963 XmlUtils.skipCurrentTag(parser);
5964 }
5965 }
5966
5967 str.close();
5968
5969 } catch(XmlPullParserException e) {
5970 mReadMessages.append("Error reading: " + e.toString());
5971 Log.e(TAG, "Error reading package manager settings", e);
5972
5973 } catch(java.io.IOException e) {
5974 mReadMessages.append("Error reading: " + e.toString());
5975 Log.e(TAG, "Error reading package manager settings", e);
5976
5977 }
5978
5979 int N = mPendingPackages.size();
5980 for (int i=0; i<N; i++) {
5981 final PendingPackage pp = mPendingPackages.get(i);
5982 Object idObj = getUserIdLP(pp.sharedId);
5983 if (idObj != null && idObj instanceof SharedUserSetting) {
5984 PackageSetting p = getPackageLP(pp.name,
5985 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
5986 pp.pkgFlags, true, true);
5987 if (p == null) {
5988 Log.w(TAG, "Unable to create application package for "
5989 + pp.name);
5990 continue;
5991 }
5992 p.copyFrom(pp);
5993 } else if (idObj != null) {
5994 String msg = "Bad package setting: package " + pp.name
5995 + " has shared uid " + pp.sharedId
5996 + " that is not a shared uid\n";
5997 mReadMessages.append(msg);
5998 Log.e(TAG, msg);
5999 } else {
6000 String msg = "Bad package setting: package " + pp.name
6001 + " has shared uid " + pp.sharedId
6002 + " that is not defined\n";
6003 mReadMessages.append(msg);
6004 Log.e(TAG, msg);
6005 }
6006 }
6007 mPendingPackages.clear();
6008
6009 N = mPendingPreferredPackages.size();
6010 mPreferredPackages.clear();
6011 for (int i=0; i<N; i++) {
6012 final String name = mPendingPreferredPackages.get(i);
6013 final PackageSetting p = mPackages.get(name);
6014 if (p != null) {
6015 mPreferredPackages.add(p);
6016 } else {
6017 Log.w(TAG, "Unknown preferred package: " + name);
6018 }
6019 }
6020 mPendingPreferredPackages.clear();
6021
6022 mReadMessages.append("Read completed successfully: "
6023 + mPackages.size() + " packages, "
6024 + mSharedUsers.size() + " shared uids\n");
6025
6026 return true;
6027 }
6028
6029 private int readInt(XmlPullParser parser, String ns, String name,
6030 int defValue) {
6031 String v = parser.getAttributeValue(ns, name);
6032 try {
6033 if (v == null) {
6034 return defValue;
6035 }
6036 return Integer.parseInt(v);
6037 } catch (NumberFormatException e) {
6038 reportSettingsProblem(Log.WARN,
6039 "Error in package manager settings: attribute " +
6040 name + " has bad integer value " + v + " at "
6041 + parser.getPositionDescription());
6042 }
6043 return defValue;
6044 }
6045
6046 private void readPermissionsLP(HashMap<String, BasePermission> out,
6047 XmlPullParser parser)
6048 throws IOException, XmlPullParserException {
6049 int outerDepth = parser.getDepth();
6050 int type;
6051 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6052 && (type != XmlPullParser.END_TAG
6053 || parser.getDepth() > outerDepth)) {
6054 if (type == XmlPullParser.END_TAG
6055 || type == XmlPullParser.TEXT) {
6056 continue;
6057 }
6058
6059 String tagName = parser.getName();
6060 if (tagName.equals("item")) {
6061 String name = parser.getAttributeValue(null, "name");
6062 String sourcePackage = parser.getAttributeValue(null, "package");
6063 String ptype = parser.getAttributeValue(null, "type");
6064 if (name != null && sourcePackage != null) {
6065 boolean dynamic = "dynamic".equals(ptype);
6066 BasePermission bp = new BasePermission(name, sourcePackage,
6067 dynamic
6068 ? BasePermission.TYPE_DYNAMIC
6069 : BasePermission.TYPE_NORMAL);
6070 if (dynamic) {
6071 PermissionInfo pi = new PermissionInfo();
6072 pi.packageName = sourcePackage.intern();
6073 pi.name = name.intern();
6074 pi.icon = readInt(parser, null, "icon", 0);
6075 pi.nonLocalizedLabel = parser.getAttributeValue(
6076 null, "label");
6077 pi.protectionLevel = readInt(parser, null, "protection",
6078 PermissionInfo.PROTECTION_NORMAL);
6079 bp.pendingInfo = pi;
6080 }
6081 out.put(bp.name, bp);
6082 } else {
6083 reportSettingsProblem(Log.WARN,
6084 "Error in package manager settings: permissions has"
6085 + " no name at " + parser.getPositionDescription());
6086 }
6087 } else {
6088 reportSettingsProblem(Log.WARN,
6089 "Unknown element reading permissions: "
6090 + parser.getName() + " at "
6091 + parser.getPositionDescription());
6092 }
6093 XmlUtils.skipCurrentTag(parser);
6094 }
6095 }
6096
6097 private void readDisabledSysPackageLP(XmlPullParser parser)
6098 throws XmlPullParserException, IOException {
6099 String name = parser.getAttributeValue(null, "name");
6100 String codePathStr = parser.getAttributeValue(null, "codePath");
6101 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6102 if(resourcePathStr == null) {
6103 resourcePathStr = codePathStr;
6104 }
6105
6106 int pkgFlags = 0;
6107 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6108 PackageSetting ps = new PackageSetting(name,
6109 new File(codePathStr),
6110 new File(resourcePathStr), pkgFlags);
6111 String timeStampStr = parser.getAttributeValue(null, "ts");
6112 if (timeStampStr != null) {
6113 try {
6114 long timeStamp = Long.parseLong(timeStampStr);
6115 ps.setTimeStamp(timeStamp, timeStampStr);
6116 } catch (NumberFormatException e) {
6117 }
6118 }
6119 String idStr = parser.getAttributeValue(null, "userId");
6120 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6121 if(ps.userId <= 0) {
6122 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6123 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6124 }
6125 int outerDepth = parser.getDepth();
6126 int type;
6127 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6128 && (type != XmlPullParser.END_TAG
6129 || parser.getDepth() > outerDepth)) {
6130 if (type == XmlPullParser.END_TAG
6131 || type == XmlPullParser.TEXT) {
6132 continue;
6133 }
6134
6135 String tagName = parser.getName();
6136 if (tagName.equals("perms")) {
6137 readGrantedPermissionsLP(parser,
6138 ps.grantedPermissions);
6139 } else {
6140 reportSettingsProblem(Log.WARN,
6141 "Unknown element under <updated-package>: "
6142 + parser.getName());
6143 XmlUtils.skipCurrentTag(parser);
6144 }
6145 }
6146 mDisabledSysPackages.put(name, ps);
6147 }
6148
6149 private void readPackageLP(XmlPullParser parser)
6150 throws XmlPullParserException, IOException {
6151 String name = null;
6152 String idStr = null;
6153 String sharedIdStr = null;
6154 String codePathStr = null;
6155 String resourcePathStr = null;
6156 String systemStr = null;
6157 int pkgFlags = 0;
6158 String timeStampStr;
6159 long timeStamp = 0;
6160 PackageSettingBase packageSetting = null;
6161 try {
6162 name = parser.getAttributeValue(null, "name");
6163 idStr = parser.getAttributeValue(null, "userId");
6164 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6165 codePathStr = parser.getAttributeValue(null, "codePath");
6166 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6167 systemStr = parser.getAttributeValue(null, "system");
6168 if (systemStr != null) {
6169 if ("true".equals(systemStr)) {
6170 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6171 }
6172 } else {
6173 // Old settings that don't specify system... just treat
6174 // them as system, good enough.
6175 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6176 }
6177 timeStampStr = parser.getAttributeValue(null, "ts");
6178 if (timeStampStr != null) {
6179 try {
6180 timeStamp = Long.parseLong(timeStampStr);
6181 } catch (NumberFormatException e) {
6182 }
6183 }
6184 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6185 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6186 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6187 if (resourcePathStr == null) {
6188 resourcePathStr = codePathStr;
6189 }
6190 if (name == null) {
6191 reportSettingsProblem(Log.WARN,
6192 "Error in package manager settings: <package> has no name at "
6193 + parser.getPositionDescription());
6194 } else if (codePathStr == null) {
6195 reportSettingsProblem(Log.WARN,
6196 "Error in package manager settings: <package> has no codePath at "
6197 + parser.getPositionDescription());
6198 } else if (userId > 0) {
6199 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
6200 new File(resourcePathStr), userId, pkgFlags);
6201 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6202 + ": userId=" + userId + " pkg=" + packageSetting);
6203 if (packageSetting == null) {
6204 reportSettingsProblem(Log.ERROR,
6205 "Failure adding uid " + userId
6206 + " while parsing settings at "
6207 + parser.getPositionDescription());
6208 } else {
6209 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6210 }
6211 } else if (sharedIdStr != null) {
6212 userId = sharedIdStr != null
6213 ? Integer.parseInt(sharedIdStr) : 0;
6214 if (userId > 0) {
6215 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
6216 new File(resourcePathStr), userId, pkgFlags);
6217 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6218 mPendingPackages.add((PendingPackage) packageSetting);
6219 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6220 + ": sharedUserId=" + userId + " pkg="
6221 + packageSetting);
6222 } else {
6223 reportSettingsProblem(Log.WARN,
6224 "Error in package manager settings: package "
6225 + name + " has bad sharedId " + sharedIdStr
6226 + " at " + parser.getPositionDescription());
6227 }
6228 } else {
6229 reportSettingsProblem(Log.WARN,
6230 "Error in package manager settings: package "
6231 + name + " has bad userId " + idStr + " at "
6232 + parser.getPositionDescription());
6233 }
6234 } catch (NumberFormatException e) {
6235 reportSettingsProblem(Log.WARN,
6236 "Error in package manager settings: package "
6237 + name + " has bad userId " + idStr + " at "
6238 + parser.getPositionDescription());
6239 }
6240 if (packageSetting != null) {
6241 final String enabledStr = parser.getAttributeValue(null, "enabled");
6242 if (enabledStr != null) {
6243 if (enabledStr.equalsIgnoreCase("true")) {
6244 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
6245 } else if (enabledStr.equalsIgnoreCase("false")) {
6246 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
6247 } else if (enabledStr.equalsIgnoreCase("default")) {
6248 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6249 } else {
6250 reportSettingsProblem(Log.WARN,
6251 "Error in package manager settings: package "
6252 + name + " has bad enabled value: " + idStr
6253 + " at " + parser.getPositionDescription());
6254 }
6255 } else {
6256 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6257 }
6258 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
6259 if (installStatusStr != null) {
6260 if (installStatusStr.equalsIgnoreCase("false")) {
6261 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
6262 } else {
6263 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
6264 }
6265 }
6266
6267 int outerDepth = parser.getDepth();
6268 int type;
6269 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6270 && (type != XmlPullParser.END_TAG
6271 || parser.getDepth() > outerDepth)) {
6272 if (type == XmlPullParser.END_TAG
6273 || type == XmlPullParser.TEXT) {
6274 continue;
6275 }
6276
6277 String tagName = parser.getName();
6278 if (tagName.equals("disabled-components")) {
6279 readDisabledComponentsLP(packageSetting, parser);
6280 } else if (tagName.equals("enabled-components")) {
6281 readEnabledComponentsLP(packageSetting, parser);
6282 } else if (tagName.equals("sigs")) {
6283 packageSetting.signatures.readXml(parser, mPastSignatures);
6284 } else if (tagName.equals("perms")) {
6285 readGrantedPermissionsLP(parser,
6286 packageSetting.loadedPermissions);
6287 packageSetting.permissionsFixed = true;
6288 } else {
6289 reportSettingsProblem(Log.WARN,
6290 "Unknown element under <package>: "
6291 + parser.getName());
6292 XmlUtils.skipCurrentTag(parser);
6293 }
6294 }
6295 } else {
6296 XmlUtils.skipCurrentTag(parser);
6297 }
6298 }
6299
6300 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
6301 XmlPullParser parser)
6302 throws IOException, XmlPullParserException {
6303 int outerDepth = parser.getDepth();
6304 int type;
6305 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6306 && (type != XmlPullParser.END_TAG
6307 || parser.getDepth() > outerDepth)) {
6308 if (type == XmlPullParser.END_TAG
6309 || type == XmlPullParser.TEXT) {
6310 continue;
6311 }
6312
6313 String tagName = parser.getName();
6314 if (tagName.equals("item")) {
6315 String name = parser.getAttributeValue(null, "name");
6316 if (name != null) {
6317 packageSetting.disabledComponents.add(name.intern());
6318 } else {
6319 reportSettingsProblem(Log.WARN,
6320 "Error in package manager settings: <disabled-components> has"
6321 + " no name at " + parser.getPositionDescription());
6322 }
6323 } else {
6324 reportSettingsProblem(Log.WARN,
6325 "Unknown element under <disabled-components>: "
6326 + parser.getName());
6327 }
6328 XmlUtils.skipCurrentTag(parser);
6329 }
6330 }
6331
6332 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
6333 XmlPullParser parser)
6334 throws IOException, XmlPullParserException {
6335 int outerDepth = parser.getDepth();
6336 int type;
6337 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6338 && (type != XmlPullParser.END_TAG
6339 || parser.getDepth() > outerDepth)) {
6340 if (type == XmlPullParser.END_TAG
6341 || type == XmlPullParser.TEXT) {
6342 continue;
6343 }
6344
6345 String tagName = parser.getName();
6346 if (tagName.equals("item")) {
6347 String name = parser.getAttributeValue(null, "name");
6348 if (name != null) {
6349 packageSetting.enabledComponents.add(name.intern());
6350 } else {
6351 reportSettingsProblem(Log.WARN,
6352 "Error in package manager settings: <enabled-components> has"
6353 + " no name at " + parser.getPositionDescription());
6354 }
6355 } else {
6356 reportSettingsProblem(Log.WARN,
6357 "Unknown element under <enabled-components>: "
6358 + parser.getName());
6359 }
6360 XmlUtils.skipCurrentTag(parser);
6361 }
6362 }
6363
6364 private void readSharedUserLP(XmlPullParser parser)
6365 throws XmlPullParserException, IOException {
6366 String name = null;
6367 String idStr = null;
6368 int pkgFlags = 0;
6369 SharedUserSetting su = null;
6370 try {
6371 name = parser.getAttributeValue(null, "name");
6372 idStr = parser.getAttributeValue(null, "userId");
6373 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6374 if ("true".equals(parser.getAttributeValue(null, "system"))) {
6375 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6376 }
6377 if (name == null) {
6378 reportSettingsProblem(Log.WARN,
6379 "Error in package manager settings: <shared-user> has no name at "
6380 + parser.getPositionDescription());
6381 } else if (userId == 0) {
6382 reportSettingsProblem(Log.WARN,
6383 "Error in package manager settings: shared-user "
6384 + name + " has bad userId " + idStr + " at "
6385 + parser.getPositionDescription());
6386 } else {
6387 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
6388 reportSettingsProblem(Log.ERROR,
6389 "Occurred while parsing settings at "
6390 + parser.getPositionDescription());
6391 }
6392 }
6393 } catch (NumberFormatException e) {
6394 reportSettingsProblem(Log.WARN,
6395 "Error in package manager settings: package "
6396 + name + " has bad userId " + idStr + " at "
6397 + parser.getPositionDescription());
6398 };
6399
6400 if (su != null) {
6401 int outerDepth = parser.getDepth();
6402 int type;
6403 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6404 && (type != XmlPullParser.END_TAG
6405 || parser.getDepth() > outerDepth)) {
6406 if (type == XmlPullParser.END_TAG
6407 || type == XmlPullParser.TEXT) {
6408 continue;
6409 }
6410
6411 String tagName = parser.getName();
6412 if (tagName.equals("sigs")) {
6413 su.signatures.readXml(parser, mPastSignatures);
6414 } else if (tagName.equals("perms")) {
6415 readGrantedPermissionsLP(parser, su.loadedPermissions);
6416 } else {
6417 reportSettingsProblem(Log.WARN,
6418 "Unknown element under <shared-user>: "
6419 + parser.getName());
6420 XmlUtils.skipCurrentTag(parser);
6421 }
6422 }
6423
6424 } else {
6425 XmlUtils.skipCurrentTag(parser);
6426 }
6427 }
6428
6429 private void readGrantedPermissionsLP(XmlPullParser parser,
6430 HashSet<String> outPerms) throws IOException, XmlPullParserException {
6431 int outerDepth = parser.getDepth();
6432 int type;
6433 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6434 && (type != XmlPullParser.END_TAG
6435 || parser.getDepth() > outerDepth)) {
6436 if (type == XmlPullParser.END_TAG
6437 || type == XmlPullParser.TEXT) {
6438 continue;
6439 }
6440
6441 String tagName = parser.getName();
6442 if (tagName.equals("item")) {
6443 String name = parser.getAttributeValue(null, "name");
6444 if (name != null) {
6445 outPerms.add(name.intern());
6446 } else {
6447 reportSettingsProblem(Log.WARN,
6448 "Error in package manager settings: <perms> has"
6449 + " no name at " + parser.getPositionDescription());
6450 }
6451 } else {
6452 reportSettingsProblem(Log.WARN,
6453 "Unknown element under <perms>: "
6454 + parser.getName());
6455 }
6456 XmlUtils.skipCurrentTag(parser);
6457 }
6458 }
6459
6460 private void readPreferredPackagesLP(XmlPullParser parser)
6461 throws XmlPullParserException, IOException {
6462 int outerDepth = parser.getDepth();
6463 int type;
6464 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6465 && (type != XmlPullParser.END_TAG
6466 || parser.getDepth() > outerDepth)) {
6467 if (type == XmlPullParser.END_TAG
6468 || type == XmlPullParser.TEXT) {
6469 continue;
6470 }
6471
6472 String tagName = parser.getName();
6473 if (tagName.equals("item")) {
6474 String name = parser.getAttributeValue(null, "name");
6475 if (name != null) {
6476 mPendingPreferredPackages.add(name);
6477 } else {
6478 reportSettingsProblem(Log.WARN,
6479 "Error in package manager settings: <preferred-package> has no name at "
6480 + parser.getPositionDescription());
6481 }
6482 } else {
6483 reportSettingsProblem(Log.WARN,
6484 "Unknown element under <preferred-packages>: "
6485 + parser.getName());
6486 }
6487 XmlUtils.skipCurrentTag(parser);
6488 }
6489 }
6490
6491 private void readPreferredActivitiesLP(XmlPullParser parser)
6492 throws XmlPullParserException, IOException {
6493 int outerDepth = parser.getDepth();
6494 int type;
6495 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6496 && (type != XmlPullParser.END_TAG
6497 || parser.getDepth() > outerDepth)) {
6498 if (type == XmlPullParser.END_TAG
6499 || type == XmlPullParser.TEXT) {
6500 continue;
6501 }
6502
6503 String tagName = parser.getName();
6504 if (tagName.equals("item")) {
6505 PreferredActivity pa = new PreferredActivity(parser);
6506 if (pa.mParseError == null) {
6507 mPreferredActivities.addFilter(pa);
6508 } else {
6509 reportSettingsProblem(Log.WARN,
6510 "Error in package manager settings: <preferred-activity> "
6511 + pa.mParseError + " at "
6512 + parser.getPositionDescription());
6513 }
6514 } else {
6515 reportSettingsProblem(Log.WARN,
6516 "Unknown element under <preferred-activities>: "
6517 + parser.getName());
6518 XmlUtils.skipCurrentTag(parser);
6519 }
6520 }
6521 }
6522
6523 // Returns -1 if we could not find an available UserId to assign
6524 private int newUserIdLP(Object obj) {
6525 // Let's be stupidly inefficient for now...
6526 final int N = mUserIds.size();
6527 for (int i=0; i<N; i++) {
6528 if (mUserIds.get(i) == null) {
6529 mUserIds.set(i, obj);
6530 return FIRST_APPLICATION_UID + i;
6531 }
6532 }
6533
6534 // None left?
6535 if (N >= MAX_APPLICATION_UIDS) {
6536 return -1;
6537 }
6538
6539 mUserIds.add(obj);
6540 return FIRST_APPLICATION_UID + N;
6541 }
6542
6543 public PackageSetting getDisabledSystemPkg(String name) {
6544 synchronized(mPackages) {
6545 PackageSetting ps = mDisabledSysPackages.get(name);
6546 return ps;
6547 }
6548 }
6549
6550 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
6551 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
6552 if (Config.LOGV) {
6553 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
6554 + " componentName = " + componentInfo.name);
6555 Log.v(TAG, "enabledComponents: "
6556 + Arrays.toString(packageSettings.enabledComponents.toArray()));
6557 Log.v(TAG, "disabledComponents: "
6558 + Arrays.toString(packageSettings.disabledComponents.toArray()));
6559 }
6560 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
6561 || ((componentInfo.enabled
6562 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
6563 || (componentInfo.applicationInfo.enabled
6564 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
6565 && !packageSettings.disabledComponents.contains(componentInfo.name))
6566 || packageSettings.enabledComponents.contains(componentInfo.name));
6567 }
6568 }
6569}