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