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