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