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