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