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