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