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