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