blob: 9f01c61626d32a82de5fe794d5fc75133c00b6b7 [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;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800105import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.zip.ZipFile;
107import java.util.zip.ZipOutputStream;
108
109class PackageManagerService extends IPackageManager.Stub {
110 private static final String TAG = "PackageManager";
111 private static final boolean DEBUG_SETTINGS = false;
112 private static final boolean DEBUG_PREFERRED = false;
113
114 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
115 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400116 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 private static final int FIRST_APPLICATION_UID =
118 Process.FIRST_APPLICATION_UID;
119 private static final int MAX_APPLICATION_UIDS = 1000;
120
121 private static final boolean SHOW_INFO = false;
122
123 private static final boolean GET_CERTIFICATES = true;
124
Oscar Montemayora8529f62009-11-18 10:14:20 -0800125 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 private static final int REMOVE_EVENTS =
128 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
129 private static final int ADD_EVENTS =
130 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
131
132 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
133
134 static final int SCAN_MONITOR = 1<<0;
135 static final int SCAN_NO_DEX = 1<<1;
136 static final int SCAN_FORCE_DEX = 1<<2;
137 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
138 static final int SCAN_FORWARD_LOCKED = 1<<4;
The Android Open Source Project10592532009-03-18 17:39:46 -0700139 static final int SCAN_NEW_INSTALL = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141 static final int LOG_BOOT_PROGRESS_PMS_START = 3060;
142 static final int LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START = 3070;
143 static final int LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START = 3080;
144 static final int LOG_BOOT_PROGRESS_PMS_SCAN_END = 3090;
145 static final int LOG_BOOT_PROGRESS_PMS_READY = 3100;
146
147 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
148 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700149 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150
Dianne Hackborn851a5412009-05-08 12:06:44 -0700151 final int mSdkVersion = Build.VERSION.SDK_INT;
152 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
153 ? null : Build.VERSION.CODENAME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154
155 final Context mContext;
156 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700157 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 final DisplayMetrics mMetrics;
159 final int mDefParseFlags;
160 final String[] mSeparateProcesses;
161
162 // This is where all application persistent data goes.
163 final File mAppDataDir;
164
Oscar Montemayora8529f62009-11-18 10:14:20 -0800165 // If Encrypted File System feature is enabled, all application persistent data
166 // should go here instead.
167 final File mSecureAppDataDir;
168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 // This is the object monitoring the framework dir.
170 final FileObserver mFrameworkInstallObserver;
171
172 // This is the object monitoring the system app dir.
173 final FileObserver mSystemInstallObserver;
174
175 // This is the object monitoring mAppInstallDir.
176 final FileObserver mAppInstallObserver;
177
178 // This is the object monitoring mDrmAppPrivateInstallDir.
179 final FileObserver mDrmAppInstallObserver;
180
181 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
182 // LOCK HELD. Can be called with mInstallLock held.
183 final Installer mInstaller;
184
185 final File mFrameworkDir;
186 final File mSystemAppDir;
187 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700188 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
191 // apps.
192 final File mDrmAppPrivateInstallDir;
193
194 // ----------------------------------------------------------------
195
196 // Lock for state used when installing and doing other long running
197 // operations. Methods that must be called with this lock held have
198 // the prefix "LI".
199 final Object mInstallLock = new Object();
200
201 // These are the directories in the 3rd party applications installed dir
202 // that we have currently loaded packages from. Keys are the application's
203 // installed zip file (absolute codePath), and values are Package.
204 final HashMap<String, PackageParser.Package> mAppDirs =
205 new HashMap<String, PackageParser.Package>();
206
207 // Information for the parser to write more useful error messages.
208 File mScanningPath;
209 int mLastScanError;
210
211 final int[] mOutPermissions = new int[3];
212
213 // ----------------------------------------------------------------
214
215 // Keys are String (package name), values are Package. This also serves
216 // as the lock for the global state. Methods that must be called with
217 // this lock held have the prefix "LP".
218 final HashMap<String, PackageParser.Package> mPackages =
219 new HashMap<String, PackageParser.Package>();
220
221 final Settings mSettings;
222 boolean mRestoredSettings;
223 boolean mReportedUidError;
224
225 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
226 int[] mGlobalGids;
227
228 // These are the built-in uid -> permission mappings that were read from the
229 // etc/permissions.xml file.
230 final SparseArray<HashSet<String>> mSystemPermissions =
231 new SparseArray<HashSet<String>>();
232
233 // These are the built-in shared libraries that were read from the
234 // etc/permissions.xml file.
235 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
236
Dianne Hackborn49237342009-08-27 20:08:01 -0700237 // Temporary for building the final shared libraries for an .apk.
238 String[] mTmpSharedLibraries = null;
239
240 // These are the features this devices supports that were read from the
241 // etc/permissions.xml file.
242 final HashMap<String, FeatureInfo> mAvailableFeatures =
243 new HashMap<String, FeatureInfo>();
244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 // All available activities, for your resolving pleasure.
246 final ActivityIntentResolver mActivities =
247 new ActivityIntentResolver();
248
249 // All available receivers, for your resolving pleasure.
250 final ActivityIntentResolver mReceivers =
251 new ActivityIntentResolver();
252
253 // All available services, for your resolving pleasure.
254 final ServiceIntentResolver mServices = new ServiceIntentResolver();
255
256 // Keys are String (provider class name), values are Provider.
257 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
258 new HashMap<ComponentName, PackageParser.Provider>();
259
260 // Mapping from provider base names (first directory in content URI codePath)
261 // to the provider information.
262 final HashMap<String, PackageParser.Provider> mProviders =
263 new HashMap<String, PackageParser.Provider>();
264
265 // Mapping from instrumentation class names to info about them.
266 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
267 new HashMap<ComponentName, PackageParser.Instrumentation>();
268
269 // Mapping from permission names to info about them.
270 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
271 new HashMap<String, PackageParser.PermissionGroup>();
272
Dianne Hackborn854060af2009-07-09 18:14:31 -0700273 // Broadcast actions that are only available to the system.
274 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 boolean mSystemReady;
277 boolean mSafeMode;
278 boolean mHasSystemUidErrors;
279
280 ApplicationInfo mAndroidApplication;
281 final ActivityInfo mResolveActivity = new ActivityInfo();
282 final ResolveInfo mResolveInfo = new ResolveInfo();
283 ComponentName mResolveComponentName;
284 PackageParser.Package mPlatformPackage;
285
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700286 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800287 final HashMap<String, ArrayList<String>> mPendingBroadcasts
288 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700289 static final int SEND_PENDING_BROADCAST = 1;
290 // Delay time in millisecs
291 static final int BROADCAST_DELAY = 10 * 1000;
292
293 class PackageHandler extends Handler {
294 PackageHandler(Looper looper) {
295 super(looper);
296 }
297 public void handleMessage(Message msg) {
298 switch (msg.what) {
299 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800300 String packages[];
301 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700302 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700303 int uids[];
304 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800305 if (mPendingBroadcasts == null) {
306 return;
307 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700308 size = mPendingBroadcasts.size();
309 if (size <= 0) {
310 // Nothing to be done. Just return
311 return;
312 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800313 packages = new String[size];
314 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700315 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800316 Iterator<HashMap.Entry<String, ArrayList<String>>>
317 it = mPendingBroadcasts.entrySet().iterator();
318 int i = 0;
319 while (it.hasNext() && i < size) {
320 HashMap.Entry<String, ArrayList<String>> ent = it.next();
321 packages[i] = ent.getKey();
322 components[i] = ent.getValue();
323 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700324 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800325 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700326 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800327 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700328 mPendingBroadcasts.clear();
329 }
330 // Send broadcasts
331 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800332 sendPackageChangedBroadcast(packages[i], true,
333 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700334 }
335 break;
336 }
337 }
338 }
339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 public static final IPackageManager main(Context context, boolean factoryTest) {
341 PackageManagerService m = new PackageManagerService(context, factoryTest);
342 ServiceManager.addService("package", m);
343 return m;
344 }
345
346 static String[] splitString(String str, char sep) {
347 int count = 1;
348 int i = 0;
349 while ((i=str.indexOf(sep, i)) >= 0) {
350 count++;
351 i++;
352 }
353
354 String[] res = new String[count];
355 i=0;
356 count = 0;
357 int lastI=0;
358 while ((i=str.indexOf(sep, i)) >= 0) {
359 res[count] = str.substring(lastI, i);
360 count++;
361 i++;
362 lastI = i;
363 }
364 res[count] = str.substring(lastI, str.length());
365 return res;
366 }
367
368 public PackageManagerService(Context context, boolean factoryTest) {
369 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
370 SystemClock.uptimeMillis());
371
372 if (mSdkVersion <= 0) {
373 Log.w(TAG, "**** ro.build.version.sdk not set!");
374 }
375
376 mContext = context;
377 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700378 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 mMetrics = new DisplayMetrics();
380 mSettings = new Settings();
381 mSettings.addSharedUserLP("android.uid.system",
382 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
383 mSettings.addSharedUserLP("android.uid.phone",
384 MULTIPLE_APPLICATION_UIDS
385 ? RADIO_UID : FIRST_APPLICATION_UID,
386 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400387 mSettings.addSharedUserLP("android.uid.log",
388 MULTIPLE_APPLICATION_UIDS
389 ? LOG_UID : FIRST_APPLICATION_UID,
390 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391
392 String separateProcesses = SystemProperties.get("debug.separate_processes");
393 if (separateProcesses != null && separateProcesses.length() > 0) {
394 if ("*".equals(separateProcesses)) {
395 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
396 mSeparateProcesses = null;
397 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
398 } else {
399 mDefParseFlags = 0;
400 mSeparateProcesses = separateProcesses.split(",");
401 Log.w(TAG, "Running with debug.separate_processes: "
402 + separateProcesses);
403 }
404 } else {
405 mDefParseFlags = 0;
406 mSeparateProcesses = null;
407 }
408
409 Installer installer = new Installer();
410 // Little hacky thing to check if installd is here, to determine
411 // whether we are running on the simulator and thus need to take
412 // care of building the /data file structure ourself.
413 // (apparently the sim now has a working installer)
414 if (installer.ping() && Process.supportsProcesses()) {
415 mInstaller = installer;
416 } else {
417 mInstaller = null;
418 }
419
420 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
421 Display d = wm.getDefaultDisplay();
422 d.getMetrics(mMetrics);
423
424 synchronized (mInstallLock) {
425 synchronized (mPackages) {
426 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700427 mHandler = new PackageHandler(mHandlerThread.getLooper());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428
429 File dataDir = Environment.getDataDirectory();
430 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800431 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
433
434 if (mInstaller == null) {
435 // Make sure these dirs exist, when we are running in
436 // the simulator.
437 // Make a wide-open directory for random misc stuff.
438 File miscDir = new File(dataDir, "misc");
439 miscDir.mkdirs();
440 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800441 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 mDrmAppPrivateInstallDir.mkdirs();
443 }
444
445 readPermissions();
446
447 mRestoredSettings = mSettings.readLP();
448 long startTime = SystemClock.uptimeMillis();
449
450 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
451 startTime);
452
453 int scanMode = SCAN_MONITOR;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700454 if (mNoDexOpt) {
455 Log.w(TAG, "Running ENG build: no pre-dexopt!");
456 scanMode |= SCAN_NO_DEX;
457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458
459 final HashSet<String> libFiles = new HashSet<String>();
460
461 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700462 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463
464 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700465 boolean didDexOpt = false;
466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 /**
468 * Out of paranoia, ensure that everything in the boot class
469 * path has been dexed.
470 */
471 String bootClassPath = System.getProperty("java.boot.class.path");
472 if (bootClassPath != null) {
473 String[] paths = splitString(bootClassPath, ':');
474 for (int i=0; i<paths.length; i++) {
475 try {
476 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
477 libFiles.add(paths[i]);
478 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700479 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 }
481 } catch (FileNotFoundException e) {
482 Log.w(TAG, "Boot class path not found: " + paths[i]);
483 } catch (IOException e) {
484 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
485 }
486 }
487 } else {
488 Log.w(TAG, "No BOOTCLASSPATH found!");
489 }
490
491 /**
492 * Also ensure all external libraries have had dexopt run on them.
493 */
494 if (mSharedLibraries.size() > 0) {
495 Iterator<String> libs = mSharedLibraries.values().iterator();
496 while (libs.hasNext()) {
497 String lib = libs.next();
498 try {
499 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
500 libFiles.add(lib);
501 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700502 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 }
504 } catch (FileNotFoundException e) {
505 Log.w(TAG, "Library not found: " + lib);
506 } catch (IOException e) {
507 Log.w(TAG, "Exception reading library: " + lib, e);
508 }
509 }
510 }
511
512 // Gross hack for now: we know this file doesn't contain any
513 // code, so don't dexopt it to avoid the resulting log spew.
514 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
515
516 /**
517 * And there are a number of commands implemented in Java, which
518 * we currently need to do the dexopt on so that they can be
519 * run from a non-root shell.
520 */
521 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700522 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 for (int i=0; i<frameworkFiles.length; i++) {
524 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
525 String path = libPath.getPath();
526 // Skip the file if we alrady did it.
527 if (libFiles.contains(path)) {
528 continue;
529 }
530 // Skip the file if it is not a type we want to dexopt.
531 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
532 continue;
533 }
534 try {
535 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
536 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700537 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 }
539 } catch (FileNotFoundException e) {
540 Log.w(TAG, "Jar not found: " + path);
541 } catch (IOException e) {
542 Log.w(TAG, "Exception reading jar: " + path, e);
543 }
544 }
545 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700546
547 if (didDexOpt) {
548 // If we had to do a dexopt of one of the previous
549 // things, then something on the system has changed.
550 // Consider this significant, and wipe away all other
551 // existing dexopt files to ensure we don't leave any
552 // dangling around.
553 String[] files = mDalvikCacheDir.list();
554 if (files != null) {
555 for (int i=0; i<files.length; i++) {
556 String fn = files[i];
557 if (fn.startsWith("data@app@")
558 || fn.startsWith("data@app-private@")) {
559 Log.i(TAG, "Pruning dalvik file: " + fn);
560 (new File(mDalvikCacheDir, fn)).delete();
561 }
562 }
563 }
564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 }
566
567 mFrameworkInstallObserver = new AppDirObserver(
568 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
569 mFrameworkInstallObserver.startWatching();
570 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
571 scanMode | SCAN_NO_DEX);
572 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
573 mSystemInstallObserver = new AppDirObserver(
574 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
575 mSystemInstallObserver.startWatching();
576 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
577 mAppInstallDir = new File(dataDir, "app");
578 if (mInstaller == null) {
579 // Make sure these dirs exist, when we are running in
580 // the simulator.
581 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
582 }
583 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800584 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 //clean up list
586 for(int i = 0; i < deletePkgsList.size(); i++) {
587 //clean up here
588 cleanupInstallFailedPackage(deletePkgsList.get(i));
589 }
590 //delete tmp files
591 deleteTempPackageFiles();
592
593 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
594 SystemClock.uptimeMillis());
595 mAppInstallObserver = new AppDirObserver(
596 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
597 mAppInstallObserver.startWatching();
598 scanDirLI(mAppInstallDir, 0, scanMode);
599
600 mDrmAppInstallObserver = new AppDirObserver(
601 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
602 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -0700603 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604
605 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
606 SystemClock.uptimeMillis());
607 Log.i(TAG, "Time to scan packages: "
608 + ((SystemClock.uptimeMillis()-startTime)/1000f)
609 + " seconds");
610
611 updatePermissionsLP();
612
613 mSettings.writeLP();
614
615 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
616 SystemClock.uptimeMillis());
617
618 // Now after opening every single application zip, make sure they
619 // are all flushed. Not really needed, but keeps things nice and
620 // tidy.
621 Runtime.getRuntime().gc();
622 } // synchronized (mPackages)
623 } // synchronized (mInstallLock)
624 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 @Override
627 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
628 throws RemoteException {
629 try {
630 return super.onTransact(code, data, reply, flags);
631 } catch (RuntimeException e) {
632 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
633 Log.e(TAG, "Package Manager Crash", e);
634 }
635 throw e;
636 }
637 }
638
Oscar Montemayora8529f62009-11-18 10:14:20 -0800639 void cleanupInstallFailedPackage(PackageSetting pkgSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800641 boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg);
642 int retCode = mInstaller.remove(pkgSettings.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 if (retCode < 0) {
644 Log.w(TAG, "Couldn't remove app data directory for package: "
Oscar Montemayora8529f62009-11-18 10:14:20 -0800645 + pkgSettings.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 }
647 } else {
648 //for emulator
Oscar Montemayora8529f62009-11-18 10:14:20 -0800649 File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 dataDir.delete();
651 }
Oscar Montemayora8529f62009-11-18 10:14:20 -0800652 mSettings.removePackageLP(pkgSettings.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 }
654
655 void readPermissions() {
656 // Read permissions from .../etc/permission directory.
657 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
658 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
659 Log.w(TAG, "No directory " + libraryDir + ", skipping");
660 return;
661 }
662 if (!libraryDir.canRead()) {
663 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
664 return;
665 }
666
667 // Iterate over the files in the directory and scan .xml files
668 for (File f : libraryDir.listFiles()) {
669 // We'll read platform.xml last
670 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
671 continue;
672 }
673
674 if (!f.getPath().endsWith(".xml")) {
675 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
676 continue;
677 }
678 if (!f.canRead()) {
679 Log.w(TAG, "Permissions library file " + f + " cannot be read");
680 continue;
681 }
682
683 readPermissionsFromXml(f);
684 }
685
686 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
687 final File permFile = new File(Environment.getRootDirectory(),
688 "etc/permissions/platform.xml");
689 readPermissionsFromXml(permFile);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700690
691 StringBuilder sb = new StringBuilder(128);
692 sb.append("Libs:");
693 Iterator<String> it = mSharedLibraries.keySet().iterator();
694 while (it.hasNext()) {
695 sb.append(' ');
696 String name = it.next();
697 sb.append(name);
698 sb.append(':');
699 sb.append(mSharedLibraries.get(name));
700 }
701 Log.i(TAG, sb.toString());
702
703 sb.setLength(0);
704 sb.append("Features:");
705 it = mAvailableFeatures.keySet().iterator();
706 while (it.hasNext()) {
707 sb.append(' ');
708 sb.append(it.next());
709 }
710 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 }
712
713 private void readPermissionsFromXml(File permFile) {
714 FileReader permReader = null;
715 try {
716 permReader = new FileReader(permFile);
717 } catch (FileNotFoundException e) {
718 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
719 return;
720 }
721
722 try {
723 XmlPullParser parser = Xml.newPullParser();
724 parser.setInput(permReader);
725
726 XmlUtils.beginDocument(parser, "permissions");
727
728 while (true) {
729 XmlUtils.nextElement(parser);
730 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
731 break;
732 }
733
734 String name = parser.getName();
735 if ("group".equals(name)) {
736 String gidStr = parser.getAttributeValue(null, "gid");
737 if (gidStr != null) {
738 int gid = Integer.parseInt(gidStr);
739 mGlobalGids = appendInt(mGlobalGids, gid);
740 } else {
741 Log.w(TAG, "<group> without gid at "
742 + parser.getPositionDescription());
743 }
744
745 XmlUtils.skipCurrentTag(parser);
746 continue;
747 } else if ("permission".equals(name)) {
748 String perm = parser.getAttributeValue(null, "name");
749 if (perm == null) {
750 Log.w(TAG, "<permission> without name at "
751 + parser.getPositionDescription());
752 XmlUtils.skipCurrentTag(parser);
753 continue;
754 }
755 perm = perm.intern();
756 readPermission(parser, perm);
757
758 } else if ("assign-permission".equals(name)) {
759 String perm = parser.getAttributeValue(null, "name");
760 if (perm == null) {
761 Log.w(TAG, "<assign-permission> without name at "
762 + parser.getPositionDescription());
763 XmlUtils.skipCurrentTag(parser);
764 continue;
765 }
766 String uidStr = parser.getAttributeValue(null, "uid");
767 if (uidStr == null) {
768 Log.w(TAG, "<assign-permission> without uid at "
769 + parser.getPositionDescription());
770 XmlUtils.skipCurrentTag(parser);
771 continue;
772 }
773 int uid = Process.getUidForName(uidStr);
774 if (uid < 0) {
775 Log.w(TAG, "<assign-permission> with unknown uid \""
776 + uidStr + "\" at "
777 + parser.getPositionDescription());
778 XmlUtils.skipCurrentTag(parser);
779 continue;
780 }
781 perm = perm.intern();
782 HashSet<String> perms = mSystemPermissions.get(uid);
783 if (perms == null) {
784 perms = new HashSet<String>();
785 mSystemPermissions.put(uid, perms);
786 }
787 perms.add(perm);
788 XmlUtils.skipCurrentTag(parser);
789
790 } else if ("library".equals(name)) {
791 String lname = parser.getAttributeValue(null, "name");
792 String lfile = parser.getAttributeValue(null, "file");
793 if (lname == null) {
794 Log.w(TAG, "<library> without name at "
795 + parser.getPositionDescription());
796 } else if (lfile == null) {
797 Log.w(TAG, "<library> without file at "
798 + parser.getPositionDescription());
799 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700800 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700801 mSharedLibraries.put(lname, lfile);
802 }
803 XmlUtils.skipCurrentTag(parser);
804 continue;
805
806 } else if ("feature".equals(name)) {
807 String fname = parser.getAttributeValue(null, "name");
808 if (fname == null) {
809 Log.w(TAG, "<feature> without name at "
810 + parser.getPositionDescription());
811 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700812 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700813 FeatureInfo fi = new FeatureInfo();
814 fi.name = fname;
815 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817 XmlUtils.skipCurrentTag(parser);
818 continue;
819
820 } else {
821 XmlUtils.skipCurrentTag(parser);
822 continue;
823 }
824
825 }
826 } catch (XmlPullParserException e) {
827 Log.w(TAG, "Got execption parsing permissions.", e);
828 } catch (IOException e) {
829 Log.w(TAG, "Got execption parsing permissions.", e);
830 }
831 }
832
833 void readPermission(XmlPullParser parser, String name)
834 throws IOException, XmlPullParserException {
835
836 name = name.intern();
837
838 BasePermission bp = mSettings.mPermissions.get(name);
839 if (bp == null) {
840 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
841 mSettings.mPermissions.put(name, bp);
842 }
843 int outerDepth = parser.getDepth();
844 int type;
845 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
846 && (type != XmlPullParser.END_TAG
847 || parser.getDepth() > outerDepth)) {
848 if (type == XmlPullParser.END_TAG
849 || type == XmlPullParser.TEXT) {
850 continue;
851 }
852
853 String tagName = parser.getName();
854 if ("group".equals(tagName)) {
855 String gidStr = parser.getAttributeValue(null, "gid");
856 if (gidStr != null) {
857 int gid = Process.getGidForName(gidStr);
858 bp.gids = appendInt(bp.gids, gid);
859 } else {
860 Log.w(TAG, "<group> without gid at "
861 + parser.getPositionDescription());
862 }
863 }
864 XmlUtils.skipCurrentTag(parser);
865 }
866 }
867
868 static int[] appendInt(int[] cur, int val) {
869 if (cur == null) {
870 return new int[] { val };
871 }
872 final int N = cur.length;
873 for (int i=0; i<N; i++) {
874 if (cur[i] == val) {
875 return cur;
876 }
877 }
878 int[] ret = new int[N+1];
879 System.arraycopy(cur, 0, ret, 0, N);
880 ret[N] = val;
881 return ret;
882 }
883
884 static int[] appendInts(int[] cur, int[] add) {
885 if (add == null) return cur;
886 if (cur == null) return add;
887 final int N = add.length;
888 for (int i=0; i<N; i++) {
889 cur = appendInt(cur, add[i]);
890 }
891 return cur;
892 }
893
894 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700895 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
896 // The package has been uninstalled but has retained data and resources.
897 return PackageParser.generatePackageInfo(p, null, flags);
898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 final PackageSetting ps = (PackageSetting)p.mExtras;
900 if (ps == null) {
901 return null;
902 }
903 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
904 return PackageParser.generatePackageInfo(p, gp.gids, flags);
905 }
906
907 public PackageInfo getPackageInfo(String packageName, int flags) {
908 synchronized (mPackages) {
909 PackageParser.Package p = mPackages.get(packageName);
910 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700911 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 + ": " + p);
913 if (p != null) {
914 return generatePackageInfo(p, flags);
915 }
916 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
917 return generatePackageInfoFromSettingsLP(packageName, flags);
918 }
919 }
920 return null;
921 }
922
923 public int getPackageUid(String packageName) {
924 synchronized (mPackages) {
925 PackageParser.Package p = mPackages.get(packageName);
926 if(p != null) {
927 return p.applicationInfo.uid;
928 }
929 PackageSetting ps = mSettings.mPackages.get(packageName);
930 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
931 return -1;
932 }
933 p = ps.pkg;
934 return p != null ? p.applicationInfo.uid : -1;
935 }
936 }
937
938 public int[] getPackageGids(String packageName) {
939 synchronized (mPackages) {
940 PackageParser.Package p = mPackages.get(packageName);
941 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700942 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 + ": " + p);
944 if (p != null) {
945 final PackageSetting ps = (PackageSetting)p.mExtras;
946 final SharedUserSetting suid = ps.sharedUser;
947 return suid != null ? suid.gids : ps.gids;
948 }
949 }
950 // stupid thing to indicate an error.
951 return new int[0];
952 }
953
954 public PermissionInfo getPermissionInfo(String name, int flags) {
955 synchronized (mPackages) {
956 final BasePermission p = mSettings.mPermissions.get(name);
957 if (p != null && p.perm != null) {
958 return PackageParser.generatePermissionInfo(p.perm, flags);
959 }
960 return null;
961 }
962 }
963
964 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
965 synchronized (mPackages) {
966 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
967 for (BasePermission p : mSettings.mPermissions.values()) {
968 if (group == null) {
969 if (p.perm.info.group == null) {
970 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
971 }
972 } else {
973 if (group.equals(p.perm.info.group)) {
974 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
975 }
976 }
977 }
978
979 if (out.size() > 0) {
980 return out;
981 }
982 return mPermissionGroups.containsKey(group) ? out : null;
983 }
984 }
985
986 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
987 synchronized (mPackages) {
988 return PackageParser.generatePermissionGroupInfo(
989 mPermissionGroups.get(name), flags);
990 }
991 }
992
993 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
994 synchronized (mPackages) {
995 final int N = mPermissionGroups.size();
996 ArrayList<PermissionGroupInfo> out
997 = new ArrayList<PermissionGroupInfo>(N);
998 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
999 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1000 }
1001 return out;
1002 }
1003 }
1004
1005 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1006 PackageSetting ps = mSettings.mPackages.get(packageName);
1007 if(ps != null) {
1008 if(ps.pkg == null) {
1009 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1010 if(pInfo != null) {
1011 return pInfo.applicationInfo;
1012 }
1013 return null;
1014 }
1015 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1016 }
1017 return null;
1018 }
1019
1020 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1021 PackageSetting ps = mSettings.mPackages.get(packageName);
1022 if(ps != null) {
1023 if(ps.pkg == null) {
1024 ps.pkg = new PackageParser.Package(packageName);
1025 ps.pkg.applicationInfo.packageName = packageName;
1026 }
1027 return generatePackageInfo(ps.pkg, flags);
1028 }
1029 return null;
1030 }
1031
1032 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1033 synchronized (mPackages) {
1034 PackageParser.Package p = mPackages.get(packageName);
1035 if (Config.LOGV) Log.v(
1036 TAG, "getApplicationInfo " + packageName
1037 + ": " + p);
1038 if (p != null) {
1039 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001040 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 }
1042 if ("android".equals(packageName)||"system".equals(packageName)) {
1043 return mAndroidApplication;
1044 }
1045 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1046 return generateApplicationInfoFromSettingsLP(packageName, flags);
1047 }
1048 }
1049 return null;
1050 }
1051
1052
1053 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1054 mContext.enforceCallingOrSelfPermission(
1055 android.Manifest.permission.CLEAR_APP_CACHE, null);
1056 // Queue up an async operation since clearing cache may take a little while.
1057 mHandler.post(new Runnable() {
1058 public void run() {
1059 mHandler.removeCallbacks(this);
1060 int retCode = -1;
1061 if (mInstaller != null) {
1062 retCode = mInstaller.freeCache(freeStorageSize);
1063 if (retCode < 0) {
1064 Log.w(TAG, "Couldn't clear application caches");
1065 }
1066 } //end if mInstaller
1067 if (observer != null) {
1068 try {
1069 observer.onRemoveCompleted(null, (retCode >= 0));
1070 } catch (RemoteException e) {
1071 Log.w(TAG, "RemoveException when invoking call back");
1072 }
1073 }
1074 }
1075 });
1076 }
1077
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001078 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001079 mContext.enforceCallingOrSelfPermission(
1080 android.Manifest.permission.CLEAR_APP_CACHE, null);
1081 // Queue up an async operation since clearing cache may take a little while.
1082 mHandler.post(new Runnable() {
1083 public void run() {
1084 mHandler.removeCallbacks(this);
1085 int retCode = -1;
1086 if (mInstaller != null) {
1087 retCode = mInstaller.freeCache(freeStorageSize);
1088 if (retCode < 0) {
1089 Log.w(TAG, "Couldn't clear application caches");
1090 }
1091 }
1092 if(pi != null) {
1093 try {
1094 // Callback via pending intent
1095 int code = (retCode >= 0) ? 1 : 0;
1096 pi.sendIntent(null, code, null,
1097 null, null);
1098 } catch (SendIntentException e1) {
1099 Log.i(TAG, "Failed to send pending intent");
1100 }
1101 }
1102 }
1103 });
1104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105
1106 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1107 synchronized (mPackages) {
1108 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001109
1110 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001112 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 }
1114 if (mResolveComponentName.equals(component)) {
1115 return mResolveActivity;
1116 }
1117 }
1118 return null;
1119 }
1120
1121 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1122 synchronized (mPackages) {
1123 PackageParser.Activity a = mReceivers.mActivities.get(component);
1124 if (Config.LOGV) Log.v(
1125 TAG, "getReceiverInfo " + component + ": " + a);
1126 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1127 return PackageParser.generateActivityInfo(a, flags);
1128 }
1129 }
1130 return null;
1131 }
1132
1133 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1134 synchronized (mPackages) {
1135 PackageParser.Service s = mServices.mServices.get(component);
1136 if (Config.LOGV) Log.v(
1137 TAG, "getServiceInfo " + component + ": " + s);
1138 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1139 return PackageParser.generateServiceInfo(s, flags);
1140 }
1141 }
1142 return null;
1143 }
1144
1145 public String[] getSystemSharedLibraryNames() {
1146 Set<String> libSet;
1147 synchronized (mPackages) {
1148 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001149 int size = libSet.size();
1150 if (size > 0) {
1151 String[] libs = new String[size];
1152 libSet.toArray(libs);
1153 return libs;
1154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001156 return null;
1157 }
1158
1159 public FeatureInfo[] getSystemAvailableFeatures() {
1160 Collection<FeatureInfo> featSet;
1161 synchronized (mPackages) {
1162 featSet = mAvailableFeatures.values();
1163 int size = featSet.size();
1164 if (size > 0) {
1165 FeatureInfo[] features = new FeatureInfo[size+1];
1166 featSet.toArray(features);
1167 FeatureInfo fi = new FeatureInfo();
1168 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1169 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1170 features[size] = fi;
1171 return features;
1172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 }
1174 return null;
1175 }
1176
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001177 public boolean hasSystemFeature(String name) {
1178 synchronized (mPackages) {
1179 return mAvailableFeatures.containsKey(name);
1180 }
1181 }
1182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 public int checkPermission(String permName, String pkgName) {
1184 synchronized (mPackages) {
1185 PackageParser.Package p = mPackages.get(pkgName);
1186 if (p != null && p.mExtras != null) {
1187 PackageSetting ps = (PackageSetting)p.mExtras;
1188 if (ps.sharedUser != null) {
1189 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1190 return PackageManager.PERMISSION_GRANTED;
1191 }
1192 } else if (ps.grantedPermissions.contains(permName)) {
1193 return PackageManager.PERMISSION_GRANTED;
1194 }
1195 }
1196 }
1197 return PackageManager.PERMISSION_DENIED;
1198 }
1199
1200 public int checkUidPermission(String permName, int uid) {
1201 synchronized (mPackages) {
1202 Object obj = mSettings.getUserIdLP(uid);
1203 if (obj != null) {
1204 if (obj instanceof SharedUserSetting) {
1205 SharedUserSetting sus = (SharedUserSetting)obj;
1206 if (sus.grantedPermissions.contains(permName)) {
1207 return PackageManager.PERMISSION_GRANTED;
1208 }
1209 } else if (obj instanceof PackageSetting) {
1210 PackageSetting ps = (PackageSetting)obj;
1211 if (ps.grantedPermissions.contains(permName)) {
1212 return PackageManager.PERMISSION_GRANTED;
1213 }
1214 }
1215 } else {
1216 HashSet<String> perms = mSystemPermissions.get(uid);
1217 if (perms != null && perms.contains(permName)) {
1218 return PackageManager.PERMISSION_GRANTED;
1219 }
1220 }
1221 }
1222 return PackageManager.PERMISSION_DENIED;
1223 }
1224
1225 private BasePermission findPermissionTreeLP(String permName) {
1226 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1227 if (permName.startsWith(bp.name) &&
1228 permName.length() > bp.name.length() &&
1229 permName.charAt(bp.name.length()) == '.') {
1230 return bp;
1231 }
1232 }
1233 return null;
1234 }
1235
1236 private BasePermission checkPermissionTreeLP(String permName) {
1237 if (permName != null) {
1238 BasePermission bp = findPermissionTreeLP(permName);
1239 if (bp != null) {
1240 if (bp.uid == Binder.getCallingUid()) {
1241 return bp;
1242 }
1243 throw new SecurityException("Calling uid "
1244 + Binder.getCallingUid()
1245 + " is not allowed to add to permission tree "
1246 + bp.name + " owned by uid " + bp.uid);
1247 }
1248 }
1249 throw new SecurityException("No permission tree found for " + permName);
1250 }
1251
1252 public boolean addPermission(PermissionInfo info) {
1253 synchronized (mPackages) {
1254 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1255 throw new SecurityException("Label must be specified in permission");
1256 }
1257 BasePermission tree = checkPermissionTreeLP(info.name);
1258 BasePermission bp = mSettings.mPermissions.get(info.name);
1259 boolean added = bp == null;
1260 if (added) {
1261 bp = new BasePermission(info.name, tree.sourcePackage,
1262 BasePermission.TYPE_DYNAMIC);
1263 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1264 throw new SecurityException(
1265 "Not allowed to modify non-dynamic permission "
1266 + info.name);
1267 }
1268 bp.perm = new PackageParser.Permission(tree.perm.owner,
1269 new PermissionInfo(info));
1270 bp.perm.info.packageName = tree.perm.info.packageName;
1271 bp.uid = tree.uid;
1272 if (added) {
1273 mSettings.mPermissions.put(info.name, bp);
1274 }
1275 mSettings.writeLP();
1276 return added;
1277 }
1278 }
1279
1280 public void removePermission(String name) {
1281 synchronized (mPackages) {
1282 checkPermissionTreeLP(name);
1283 BasePermission bp = mSettings.mPermissions.get(name);
1284 if (bp != null) {
1285 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1286 throw new SecurityException(
1287 "Not allowed to modify non-dynamic permission "
1288 + name);
1289 }
1290 mSettings.mPermissions.remove(name);
1291 mSettings.writeLP();
1292 }
1293 }
1294 }
1295
Dianne Hackborn854060af2009-07-09 18:14:31 -07001296 public boolean isProtectedBroadcast(String actionName) {
1297 synchronized (mPackages) {
1298 return mProtectedBroadcasts.contains(actionName);
1299 }
1300 }
1301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 public int checkSignatures(String pkg1, String pkg2) {
1303 synchronized (mPackages) {
1304 PackageParser.Package p1 = mPackages.get(pkg1);
1305 PackageParser.Package p2 = mPackages.get(pkg2);
1306 if (p1 == null || p1.mExtras == null
1307 || p2 == null || p2.mExtras == null) {
1308 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1309 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001310 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 }
1312 }
1313
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001314 public int checkUidSignatures(int uid1, int uid2) {
1315 synchronized (mPackages) {
1316 Signature[] s1;
1317 Signature[] s2;
1318 Object obj = mSettings.getUserIdLP(uid1);
1319 if (obj != null) {
1320 if (obj instanceof SharedUserSetting) {
1321 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1322 } else if (obj instanceof PackageSetting) {
1323 s1 = ((PackageSetting)obj).signatures.mSignatures;
1324 } else {
1325 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1326 }
1327 } else {
1328 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1329 }
1330 obj = mSettings.getUserIdLP(uid2);
1331 if (obj != null) {
1332 if (obj instanceof SharedUserSetting) {
1333 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1334 } else if (obj instanceof PackageSetting) {
1335 s2 = ((PackageSetting)obj).signatures.mSignatures;
1336 } else {
1337 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1338 }
1339 } else {
1340 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1341 }
1342 return checkSignaturesLP(s1, s2);
1343 }
1344 }
1345
1346 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1347 if (s1 == null) {
1348 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1350 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1351 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001352 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1354 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001355 final int N1 = s1.length;
1356 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 for (int i=0; i<N1; i++) {
1358 boolean match = false;
1359 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001360 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 match = true;
1362 break;
1363 }
1364 }
1365 if (!match) {
1366 return PackageManager.SIGNATURE_NO_MATCH;
1367 }
1368 }
1369 return PackageManager.SIGNATURE_MATCH;
1370 }
1371
1372 public String[] getPackagesForUid(int uid) {
1373 synchronized (mPackages) {
1374 Object obj = mSettings.getUserIdLP(uid);
1375 if (obj instanceof SharedUserSetting) {
1376 SharedUserSetting sus = (SharedUserSetting)obj;
1377 final int N = sus.packages.size();
1378 String[] res = new String[N];
1379 Iterator<PackageSetting> it = sus.packages.iterator();
1380 int i=0;
1381 while (it.hasNext()) {
1382 res[i++] = it.next().name;
1383 }
1384 return res;
1385 } else if (obj instanceof PackageSetting) {
1386 PackageSetting ps = (PackageSetting)obj;
1387 return new String[] { ps.name };
1388 }
1389 }
1390 return null;
1391 }
1392
1393 public String getNameForUid(int uid) {
1394 synchronized (mPackages) {
1395 Object obj = mSettings.getUserIdLP(uid);
1396 if (obj instanceof SharedUserSetting) {
1397 SharedUserSetting sus = (SharedUserSetting)obj;
1398 return sus.name + ":" + sus.userId;
1399 } else if (obj instanceof PackageSetting) {
1400 PackageSetting ps = (PackageSetting)obj;
1401 return ps.name;
1402 }
1403 }
1404 return null;
1405 }
1406
1407 public int getUidForSharedUser(String sharedUserName) {
1408 if(sharedUserName == null) {
1409 return -1;
1410 }
1411 synchronized (mPackages) {
1412 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1413 if(suid == null) {
1414 return -1;
1415 }
1416 return suid.userId;
1417 }
1418 }
1419
1420 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1421 int flags) {
1422 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001423 return chooseBestActivity(intent, resolvedType, flags, query);
1424 }
1425
Mihai Predaeae850c2009-05-13 10:13:48 +02001426 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1427 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 if (query != null) {
1429 final int N = query.size();
1430 if (N == 1) {
1431 return query.get(0);
1432 } else if (N > 1) {
1433 // If there is more than one activity with the same priority,
1434 // then let the user decide between them.
1435 ResolveInfo r0 = query.get(0);
1436 ResolveInfo r1 = query.get(1);
1437 if (false) {
1438 System.out.println(r0.activityInfo.name +
1439 "=" + r0.priority + " vs " +
1440 r1.activityInfo.name +
1441 "=" + r1.priority);
1442 }
1443 // If the first activity has a higher priority, or a different
1444 // default, then it is always desireable to pick it.
1445 if (r0.priority != r1.priority
1446 || r0.preferredOrder != r1.preferredOrder
1447 || r0.isDefault != r1.isDefault) {
1448 return query.get(0);
1449 }
1450 // If we have saved a preference for a preferred activity for
1451 // this Intent, use that.
1452 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1453 flags, query, r0.priority);
1454 if (ri != null) {
1455 return ri;
1456 }
1457 return mResolveInfo;
1458 }
1459 }
1460 return null;
1461 }
1462
1463 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1464 int flags, List<ResolveInfo> query, int priority) {
1465 synchronized (mPackages) {
1466 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1467 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001468 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1470 if (prefs != null && prefs.size() > 0) {
1471 // First figure out how good the original match set is.
1472 // We will only allow preferred activities that came
1473 // from the same match quality.
1474 int match = 0;
1475 final int N = query.size();
1476 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1477 for (int j=0; j<N; j++) {
1478 ResolveInfo ri = query.get(j);
1479 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1480 + ": 0x" + Integer.toHexString(match));
1481 if (ri.match > match) match = ri.match;
1482 }
1483 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1484 + Integer.toHexString(match));
1485 match &= IntentFilter.MATCH_CATEGORY_MASK;
1486 final int M = prefs.size();
1487 for (int i=0; i<M; i++) {
1488 PreferredActivity pa = prefs.get(i);
1489 if (pa.mMatch != match) {
1490 continue;
1491 }
1492 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1493 if (DEBUG_PREFERRED) {
1494 Log.v(TAG, "Got preferred activity:");
1495 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1496 }
1497 if (ai != null) {
1498 for (int j=0; j<N; j++) {
1499 ResolveInfo ri = query.get(j);
1500 if (!ri.activityInfo.applicationInfo.packageName
1501 .equals(ai.applicationInfo.packageName)) {
1502 continue;
1503 }
1504 if (!ri.activityInfo.name.equals(ai.name)) {
1505 continue;
1506 }
1507
1508 // Okay we found a previously set preferred app.
1509 // If the result set is different from when this
1510 // was created, we need to clear it and re-ask the
1511 // user their preference.
1512 if (!pa.sameSet(query, priority)) {
1513 Log.i(TAG, "Result set changed, dropping preferred activity for "
1514 + intent + " type " + resolvedType);
1515 mSettings.mPreferredActivities.removeFilter(pa);
1516 return null;
1517 }
1518
1519 // Yay!
1520 return ri;
1521 }
1522 }
1523 }
1524 }
1525 }
1526 return null;
1527 }
1528
1529 public List<ResolveInfo> queryIntentActivities(Intent intent,
1530 String resolvedType, int flags) {
1531 ComponentName comp = intent.getComponent();
1532 if (comp != null) {
1533 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1534 ActivityInfo ai = getActivityInfo(comp, flags);
1535 if (ai != null) {
1536 ResolveInfo ri = new ResolveInfo();
1537 ri.activityInfo = ai;
1538 list.add(ri);
1539 }
1540 return list;
1541 }
1542
1543 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001544 String pkgName = intent.getPackage();
1545 if (pkgName == null) {
1546 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1547 resolvedType, flags);
1548 }
1549 PackageParser.Package pkg = mPackages.get(pkgName);
1550 if (pkg != null) {
1551 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1552 resolvedType, flags, pkg.activities);
1553 }
1554 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 }
1556 }
1557
1558 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1559 Intent[] specifics, String[] specificTypes, Intent intent,
1560 String resolvedType, int flags) {
1561 final String resultsAction = intent.getAction();
1562
1563 List<ResolveInfo> results = queryIntentActivities(
1564 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1565 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1566
1567 int specificsPos = 0;
1568 int N;
1569
1570 // todo: note that the algorithm used here is O(N^2). This
1571 // isn't a problem in our current environment, but if we start running
1572 // into situations where we have more than 5 or 10 matches then this
1573 // should probably be changed to something smarter...
1574
1575 // First we go through and resolve each of the specific items
1576 // that were supplied, taking care of removing any corresponding
1577 // duplicate items in the generic resolve list.
1578 if (specifics != null) {
1579 for (int i=0; i<specifics.length; i++) {
1580 final Intent sintent = specifics[i];
1581 if (sintent == null) {
1582 continue;
1583 }
1584
1585 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1586 String action = sintent.getAction();
1587 if (resultsAction != null && resultsAction.equals(action)) {
1588 // If this action was explicitly requested, then don't
1589 // remove things that have it.
1590 action = null;
1591 }
1592 ComponentName comp = sintent.getComponent();
1593 ResolveInfo ri = null;
1594 ActivityInfo ai = null;
1595 if (comp == null) {
1596 ri = resolveIntent(
1597 sintent,
1598 specificTypes != null ? specificTypes[i] : null,
1599 flags);
1600 if (ri == null) {
1601 continue;
1602 }
1603 if (ri == mResolveInfo) {
1604 // ACK! Must do something better with this.
1605 }
1606 ai = ri.activityInfo;
1607 comp = new ComponentName(ai.applicationInfo.packageName,
1608 ai.name);
1609 } else {
1610 ai = getActivityInfo(comp, flags);
1611 if (ai == null) {
1612 continue;
1613 }
1614 }
1615
1616 // Look for any generic query activities that are duplicates
1617 // of this specific one, and remove them from the results.
1618 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1619 N = results.size();
1620 int j;
1621 for (j=specificsPos; j<N; j++) {
1622 ResolveInfo sri = results.get(j);
1623 if ((sri.activityInfo.name.equals(comp.getClassName())
1624 && sri.activityInfo.applicationInfo.packageName.equals(
1625 comp.getPackageName()))
1626 || (action != null && sri.filter.matchAction(action))) {
1627 results.remove(j);
1628 if (Config.LOGV) Log.v(
1629 TAG, "Removing duplicate item from " + j
1630 + " due to specific " + specificsPos);
1631 if (ri == null) {
1632 ri = sri;
1633 }
1634 j--;
1635 N--;
1636 }
1637 }
1638
1639 // Add this specific item to its proper place.
1640 if (ri == null) {
1641 ri = new ResolveInfo();
1642 ri.activityInfo = ai;
1643 }
1644 results.add(specificsPos, ri);
1645 ri.specificIndex = i;
1646 specificsPos++;
1647 }
1648 }
1649
1650 // Now we go through the remaining generic results and remove any
1651 // duplicate actions that are found here.
1652 N = results.size();
1653 for (int i=specificsPos; i<N-1; i++) {
1654 final ResolveInfo rii = results.get(i);
1655 if (rii.filter == null) {
1656 continue;
1657 }
1658
1659 // Iterate over all of the actions of this result's intent
1660 // filter... typically this should be just one.
1661 final Iterator<String> it = rii.filter.actionsIterator();
1662 if (it == null) {
1663 continue;
1664 }
1665 while (it.hasNext()) {
1666 final String action = it.next();
1667 if (resultsAction != null && resultsAction.equals(action)) {
1668 // If this action was explicitly requested, then don't
1669 // remove things that have it.
1670 continue;
1671 }
1672 for (int j=i+1; j<N; j++) {
1673 final ResolveInfo rij = results.get(j);
1674 if (rij.filter != null && rij.filter.hasAction(action)) {
1675 results.remove(j);
1676 if (Config.LOGV) Log.v(
1677 TAG, "Removing duplicate item from " + j
1678 + " due to action " + action + " at " + i);
1679 j--;
1680 N--;
1681 }
1682 }
1683 }
1684
1685 // If the caller didn't request filter information, drop it now
1686 // so we don't have to marshall/unmarshall it.
1687 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1688 rii.filter = null;
1689 }
1690 }
1691
1692 // Filter out the caller activity if so requested.
1693 if (caller != null) {
1694 N = results.size();
1695 for (int i=0; i<N; i++) {
1696 ActivityInfo ainfo = results.get(i).activityInfo;
1697 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1698 && caller.getClassName().equals(ainfo.name)) {
1699 results.remove(i);
1700 break;
1701 }
1702 }
1703 }
1704
1705 // If the caller didn't request filter information,
1706 // drop them now so we don't have to
1707 // marshall/unmarshall it.
1708 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1709 N = results.size();
1710 for (int i=0; i<N; i++) {
1711 results.get(i).filter = null;
1712 }
1713 }
1714
1715 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1716 return results;
1717 }
1718
1719 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1720 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001721 ComponentName comp = intent.getComponent();
1722 if (comp != null) {
1723 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1724 ActivityInfo ai = getReceiverInfo(comp, flags);
1725 if (ai != null) {
1726 ResolveInfo ri = new ResolveInfo();
1727 ri.activityInfo = ai;
1728 list.add(ri);
1729 }
1730 return list;
1731 }
1732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001734 String pkgName = intent.getPackage();
1735 if (pkgName == null) {
1736 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1737 resolvedType, flags);
1738 }
1739 PackageParser.Package pkg = mPackages.get(pkgName);
1740 if (pkg != null) {
1741 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1742 resolvedType, flags, pkg.receivers);
1743 }
1744 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 }
1746 }
1747
1748 public ResolveInfo resolveService(Intent intent, String resolvedType,
1749 int flags) {
1750 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1751 flags);
1752 if (query != null) {
1753 if (query.size() >= 1) {
1754 // If there is more than one service with the same priority,
1755 // just arbitrarily pick the first one.
1756 return query.get(0);
1757 }
1758 }
1759 return null;
1760 }
1761
1762 public List<ResolveInfo> queryIntentServices(Intent intent,
1763 String resolvedType, int flags) {
1764 ComponentName comp = intent.getComponent();
1765 if (comp != null) {
1766 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1767 ServiceInfo si = getServiceInfo(comp, flags);
1768 if (si != null) {
1769 ResolveInfo ri = new ResolveInfo();
1770 ri.serviceInfo = si;
1771 list.add(ri);
1772 }
1773 return list;
1774 }
1775
1776 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001777 String pkgName = intent.getPackage();
1778 if (pkgName == null) {
1779 return (List<ResolveInfo>)mServices.queryIntent(intent,
1780 resolvedType, flags);
1781 }
1782 PackageParser.Package pkg = mPackages.get(pkgName);
1783 if (pkg != null) {
1784 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1785 resolvedType, flags, pkg.services);
1786 }
1787 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 }
1789 }
1790
1791 public List<PackageInfo> getInstalledPackages(int flags) {
1792 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1793
1794 synchronized (mPackages) {
1795 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1796 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1797 while (i.hasNext()) {
1798 final PackageSetting ps = i.next();
1799 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1800 if(psPkg != null) {
1801 finalList.add(psPkg);
1802 }
1803 }
1804 }
1805 else {
1806 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1807 while (i.hasNext()) {
1808 final PackageParser.Package p = i.next();
1809 if (p.applicationInfo != null) {
1810 PackageInfo pi = generatePackageInfo(p, flags);
1811 if(pi != null) {
1812 finalList.add(pi);
1813 }
1814 }
1815 }
1816 }
1817 }
1818 return finalList;
1819 }
1820
1821 public List<ApplicationInfo> getInstalledApplications(int flags) {
1822 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1823 synchronized(mPackages) {
1824 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1825 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1826 while (i.hasNext()) {
1827 final PackageSetting ps = i.next();
1828 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1829 if(ai != null) {
1830 finalList.add(ai);
1831 }
1832 }
1833 }
1834 else {
1835 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1836 while (i.hasNext()) {
1837 final PackageParser.Package p = i.next();
1838 if (p.applicationInfo != null) {
1839 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1840 if(ai != null) {
1841 finalList.add(ai);
1842 }
1843 }
1844 }
1845 }
1846 }
1847 return finalList;
1848 }
1849
1850 public List<ApplicationInfo> getPersistentApplications(int flags) {
1851 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1852
1853 synchronized (mPackages) {
1854 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1855 while (i.hasNext()) {
1856 PackageParser.Package p = i.next();
1857 if (p.applicationInfo != null
1858 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1859 && (!mSafeMode || (p.applicationInfo.flags
1860 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1861 finalList.add(p.applicationInfo);
1862 }
1863 }
1864 }
1865
1866 return finalList;
1867 }
1868
1869 public ProviderInfo resolveContentProvider(String name, int flags) {
1870 synchronized (mPackages) {
1871 final PackageParser.Provider provider = mProviders.get(name);
1872 return provider != null
1873 && mSettings.isEnabledLP(provider.info, flags)
1874 && (!mSafeMode || (provider.info.applicationInfo.flags
1875 &ApplicationInfo.FLAG_SYSTEM) != 0)
1876 ? PackageParser.generateProviderInfo(provider, flags)
1877 : null;
1878 }
1879 }
1880
Fred Quintana718d8a22009-04-29 17:53:20 -07001881 /**
1882 * @deprecated
1883 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 public void querySyncProviders(List outNames, List outInfo) {
1885 synchronized (mPackages) {
1886 Iterator<Map.Entry<String, PackageParser.Provider>> i
1887 = mProviders.entrySet().iterator();
1888
1889 while (i.hasNext()) {
1890 Map.Entry<String, PackageParser.Provider> entry = i.next();
1891 PackageParser.Provider p = entry.getValue();
1892
1893 if (p.syncable
1894 && (!mSafeMode || (p.info.applicationInfo.flags
1895 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1896 outNames.add(entry.getKey());
1897 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1898 }
1899 }
1900 }
1901 }
1902
1903 public List<ProviderInfo> queryContentProviders(String processName,
1904 int uid, int flags) {
1905 ArrayList<ProviderInfo> finalList = null;
1906
1907 synchronized (mPackages) {
1908 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1909 while (i.hasNext()) {
1910 PackageParser.Provider p = i.next();
1911 if (p.info.authority != null
1912 && (processName == null ||
1913 (p.info.processName.equals(processName)
1914 && p.info.applicationInfo.uid == uid))
1915 && mSettings.isEnabledLP(p.info, flags)
1916 && (!mSafeMode || (p.info.applicationInfo.flags
1917 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1918 if (finalList == null) {
1919 finalList = new ArrayList<ProviderInfo>(3);
1920 }
1921 finalList.add(PackageParser.generateProviderInfo(p,
1922 flags));
1923 }
1924 }
1925 }
1926
1927 if (finalList != null) {
1928 Collections.sort(finalList, mProviderInitOrderSorter);
1929 }
1930
1931 return finalList;
1932 }
1933
1934 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1935 int flags) {
1936 synchronized (mPackages) {
1937 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1938 return PackageParser.generateInstrumentationInfo(i, flags);
1939 }
1940 }
1941
1942 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1943 int flags) {
1944 ArrayList<InstrumentationInfo> finalList =
1945 new ArrayList<InstrumentationInfo>();
1946
1947 synchronized (mPackages) {
1948 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1949 while (i.hasNext()) {
1950 PackageParser.Instrumentation p = i.next();
1951 if (targetPackage == null
1952 || targetPackage.equals(p.info.targetPackage)) {
1953 finalList.add(PackageParser.generateInstrumentationInfo(p,
1954 flags));
1955 }
1956 }
1957 }
1958
1959 return finalList;
1960 }
1961
1962 private void scanDirLI(File dir, int flags, int scanMode) {
1963 Log.d(TAG, "Scanning app dir " + dir);
1964
1965 String[] files = dir.list();
1966
1967 int i;
1968 for (i=0; i<files.length; i++) {
1969 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001970 File resFile = file;
1971 // Pick up the resource path from settings for fwd locked apps
1972 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1973 resFile = null;
1974 }
1975 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1977 }
1978 }
1979
1980 private static void reportSettingsProblem(int priority, String msg) {
1981 try {
1982 File dataDir = Environment.getDataDirectory();
1983 File systemDir = new File(dataDir, "system");
1984 File fname = new File(systemDir, "uiderrors.txt");
1985 FileOutputStream out = new FileOutputStream(fname, true);
1986 PrintWriter pw = new PrintWriter(out);
1987 pw.println(msg);
1988 pw.close();
1989 FileUtils.setPermissions(
1990 fname.toString(),
1991 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1992 -1, -1);
1993 } catch (java.io.IOException e) {
1994 }
1995 Log.println(priority, TAG, msg);
1996 }
1997
1998 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1999 PackageParser.Package pkg, File srcFile, int parseFlags) {
2000 if (GET_CERTIFICATES) {
2001 if (ps == null || !ps.codePath.equals(srcFile)
2002 || ps.getTimeStamp() != srcFile.lastModified()) {
2003 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2004 if (!pp.collectCertificates(pkg, parseFlags)) {
2005 mLastScanError = pp.getParseError();
2006 return false;
2007 }
2008 }
2009 }
2010 return true;
2011 }
2012
2013 /*
2014 * Scan a package and return the newly parsed package.
2015 * Returns null in case of errors and the error code is stored in mLastScanError
2016 */
2017 private PackageParser.Package scanPackageLI(File scanFile,
2018 File destCodeFile, File destResourceFile, int parseFlags,
2019 int scanMode) {
2020 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2021 parseFlags |= mDefParseFlags;
2022 PackageParser pp = new PackageParser(scanFile.getPath());
2023 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 final PackageParser.Package pkg = pp.parsePackage(scanFile,
2025 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
2026 if (pkg == null) {
2027 mLastScanError = pp.getParseError();
2028 return null;
2029 }
2030 PackageSetting ps;
2031 PackageSetting updatedPkg;
2032 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002033 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2035 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002036 // Verify certificates first
2037 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2038 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2039 return null;
2040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 if (updatedPkg != null) {
2042 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2043 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2044 }
2045 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2046 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002047 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2048 if (pkg.mVersionCode < ps.versionCode) {
2049 // The system package has been updated and the code path does not match
2050 // Ignore entry. Just return
2051 Log.w(TAG, "Package:" + pkg.packageName +
2052 " has been updated. Ignoring the one from path:"+scanFile);
2053 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2054 return null;
2055 } else {
2056 // Delete the older apk pointed to by ps
2057 // At this point, its safely assumed that package installation for
2058 // apps in system partition will go through. If not there won't be a working
2059 // version of the app
2060 synchronized (mPackages) {
2061 // Just remove the loaded entries from package lists.
2062 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002063 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002064 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2065 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 }
2068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 // The apk is forward locked (not public) if its code and resources
2070 // are kept in different files.
2071 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2072 scanMode |= SCAN_FORWARD_LOCKED;
2073 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002074 File resFile = destResourceFile;
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002075 if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002076 resFile = getFwdLockedResource(ps.name);
2077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002079 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2081 }
2082
2083 private static String fixProcessName(String defProcessName,
2084 String processName, int uid) {
2085 if (processName == null) {
2086 return defProcessName;
2087 }
2088 return processName;
2089 }
2090
2091 private boolean verifySignaturesLP(PackageSetting pkgSetting,
2092 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2093 if (pkg.mSignatures != null) {
2094 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2095 updateSignature)) {
2096 Log.e(TAG, "Package " + pkg.packageName
2097 + " signatures do not match the previously installed version; ignoring!");
2098 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2099 return false;
2100 }
2101
2102 if (pkgSetting.sharedUser != null) {
2103 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2104 pkg.mSignatures, updateSignature)) {
2105 Log.e(TAG, "Package " + pkg.packageName
2106 + " has no signatures that match those in shared user "
2107 + pkgSetting.sharedUser.name + "; ignoring!");
2108 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2109 return false;
2110 }
2111 }
2112 } else {
2113 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2114 }
2115 return true;
2116 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002117
2118 public boolean performDexOpt(String packageName) {
2119 if (!mNoDexOpt) {
2120 return false;
2121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002123 PackageParser.Package p;
2124 synchronized (mPackages) {
2125 p = mPackages.get(packageName);
2126 if (p == null || p.mDidDexOpt) {
2127 return false;
2128 }
2129 }
2130 synchronized (mInstallLock) {
2131 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2132 }
2133 }
2134
2135 static final int DEX_OPT_SKIPPED = 0;
2136 static final int DEX_OPT_PERFORMED = 1;
2137 static final int DEX_OPT_FAILED = -1;
2138
2139 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2140 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002141 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002142 String path = pkg.mScanPath;
2143 int ret = 0;
2144 try {
2145 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2146 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2147 !pkg.mForwardLocked);
2148 pkg.mDidDexOpt = true;
2149 performed = true;
2150 }
2151 } catch (FileNotFoundException e) {
2152 Log.w(TAG, "Apk not found for dexopt: " + path);
2153 ret = -1;
2154 } catch (IOException e) {
2155 Log.w(TAG, "Exception reading apk: " + path, e);
2156 ret = -1;
2157 }
2158 if (ret < 0) {
2159 //error from installer
2160 return DEX_OPT_FAILED;
2161 }
2162 }
2163
2164 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2165 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002166
2167 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2168 return Environment.isEncryptedFilesystemEnabled() &&
2169 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2170 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 private PackageParser.Package scanPackageLI(
2173 File scanFile, File destCodeFile, File destResourceFile,
2174 PackageParser.Package pkg, int parseFlags, int scanMode) {
2175
2176 mScanningPath = scanFile;
2177 if (pkg == null) {
2178 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2179 return null;
2180 }
2181
2182 final String pkgName = pkg.applicationInfo.packageName;
2183 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2184 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2185 }
2186
2187 if (pkgName.equals("android")) {
2188 synchronized (mPackages) {
2189 if (mAndroidApplication != null) {
2190 Log.w(TAG, "*************************************************");
2191 Log.w(TAG, "Core android package being redefined. Skipping.");
2192 Log.w(TAG, " file=" + mScanningPath);
2193 Log.w(TAG, "*************************************************");
2194 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2195 return null;
2196 }
2197
2198 // Set up information for our fall-back user intent resolution
2199 // activity.
2200 mPlatformPackage = pkg;
2201 pkg.mVersionCode = mSdkVersion;
2202 mAndroidApplication = pkg.applicationInfo;
2203 mResolveActivity.applicationInfo = mAndroidApplication;
2204 mResolveActivity.name = ResolverActivity.class.getName();
2205 mResolveActivity.packageName = mAndroidApplication.packageName;
2206 mResolveActivity.processName = mAndroidApplication.processName;
2207 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2208 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2209 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2210 mResolveActivity.exported = true;
2211 mResolveActivity.enabled = true;
2212 mResolveInfo.activityInfo = mResolveActivity;
2213 mResolveInfo.priority = 0;
2214 mResolveInfo.preferredOrder = 0;
2215 mResolveInfo.match = 0;
2216 mResolveComponentName = new ComponentName(
2217 mAndroidApplication.packageName, mResolveActivity.name);
2218 }
2219 }
2220
2221 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2222 TAG, "Scanning package " + pkgName);
2223 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2224 Log.w(TAG, "*************************************************");
2225 Log.w(TAG, "Application package " + pkgName
2226 + " already installed. Skipping duplicate.");
2227 Log.w(TAG, "*************************************************");
2228 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2229 return null;
2230 }
2231
2232 SharedUserSetting suid = null;
2233 PackageSetting pkgSetting = null;
2234
2235 boolean removeExisting = false;
2236
2237 synchronized (mPackages) {
2238 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002239 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2240 if (mTmpSharedLibraries == null ||
2241 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2242 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2243 }
2244 int num = 0;
2245 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2246 for (int i=0; i<N; i++) {
2247 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 if (file == null) {
2249 Log.e(TAG, "Package " + pkg.packageName
2250 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002251 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2253 return null;
2254 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002255 mTmpSharedLibraries[num] = file;
2256 num++;
2257 }
2258 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2259 for (int i=0; i<N; i++) {
2260 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2261 if (file == null) {
2262 Log.w(TAG, "Package " + pkg.packageName
2263 + " desires unavailable shared library "
2264 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2265 } else {
2266 mTmpSharedLibraries[num] = file;
2267 num++;
2268 }
2269 }
2270 if (num > 0) {
2271 pkg.usesLibraryFiles = new String[num];
2272 System.arraycopy(mTmpSharedLibraries, 0,
2273 pkg.usesLibraryFiles, 0, num);
2274 }
2275
2276 if (pkg.reqFeatures != null) {
2277 N = pkg.reqFeatures.size();
2278 for (int i=0; i<N; i++) {
2279 FeatureInfo fi = pkg.reqFeatures.get(i);
2280 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2281 // Don't care.
2282 continue;
2283 }
2284
2285 if (fi.name != null) {
2286 if (mAvailableFeatures.get(fi.name) == null) {
2287 Log.e(TAG, "Package " + pkg.packageName
2288 + " requires unavailable feature "
2289 + fi.name + "; failing!");
2290 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2291 return null;
2292 }
2293 }
2294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 }
2296 }
2297
2298 if (pkg.mSharedUserId != null) {
2299 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2300 pkg.applicationInfo.flags, true);
2301 if (suid == null) {
2302 Log.w(TAG, "Creating application package " + pkgName
2303 + " for shared user failed");
2304 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2305 return null;
2306 }
2307 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2308 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2309 + suid.userId + "): packages=" + suid.packages);
2310 }
2311 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002312
2313 // Just create the setting, don't add it yet. For already existing packages
2314 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2316 destResourceFile, pkg.applicationInfo.flags, true, false);
2317 if (pkgSetting == null) {
2318 Log.w(TAG, "Creating application package " + pkgName + " failed");
2319 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2320 return null;
2321 }
2322 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2323 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2324 }
2325
2326 pkg.applicationInfo.uid = pkgSetting.userId;
2327 pkg.mExtras = pkgSetting;
2328
2329 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
2330 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2331 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2332 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2333 return null;
2334 }
2335 // The signature has changed, but this package is in the system
2336 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002337 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 // However... if this package is part of a shared user, but it
2339 // doesn't match the signature of the shared user, let's fail.
2340 // What this means is that you can't change the signatures
2341 // associated with an overall shared user, which doesn't seem all
2342 // that unreasonable.
2343 if (pkgSetting.sharedUser != null) {
2344 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2345 pkg.mSignatures, false)) {
2346 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2347 return null;
2348 }
2349 }
2350 removeExisting = true;
2351 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002352
2353 // Verify that this new package doesn't have any content providers
2354 // that conflict with existing packages. Only do this if the
2355 // package isn't already installed, since we don't want to break
2356 // things that are installed.
2357 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2358 int N = pkg.providers.size();
2359 int i;
2360 for (i=0; i<N; i++) {
2361 PackageParser.Provider p = pkg.providers.get(i);
2362 String names[] = p.info.authority.split(";");
2363 for (int j = 0; j < names.length; j++) {
2364 if (mProviders.containsKey(names[j])) {
2365 PackageParser.Provider other = mProviders.get(names[j]);
2366 Log.w(TAG, "Can't install because provider name " + names[j] +
2367 " (in package " + pkg.applicationInfo.packageName +
2368 ") is already used by "
2369 + ((other != null && other.component != null)
2370 ? other.component.getPackageName() : "?"));
2371 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2372 return null;
2373 }
2374 }
2375 }
2376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 }
2378
2379 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002380 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002382 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 if (ret != 0) {
2384 String msg = "System package " + pkg.packageName
2385 + " could not have data directory erased after signature change.";
2386 reportSettingsProblem(Log.WARN, msg);
2387 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2388 return null;
2389 }
2390 }
2391 Log.w(TAG, "System package " + pkg.packageName
2392 + " signature changed: existing data removed.");
2393 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2394 }
2395
2396 long scanFileTime = scanFile.lastModified();
2397 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2398 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2399 pkg.applicationInfo.processName = fixProcessName(
2400 pkg.applicationInfo.packageName,
2401 pkg.applicationInfo.processName,
2402 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002403 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404
2405 File dataPath;
2406 if (mPlatformPackage == pkg) {
2407 // The system package is special.
2408 dataPath = new File (Environment.getDataDirectory(), "system");
2409 pkg.applicationInfo.dataDir = dataPath.getPath();
2410 } else {
2411 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002412 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2413 if (useEncryptedFSDir) {
2414 dataPath = new File(mSecureAppDataDir, pkgName);
2415 } else {
2416 dataPath = new File(mAppDataDir, pkgName);
2417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 if (dataPath.exists()) {
2419 mOutPermissions[1] = 0;
2420 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2421 if (mOutPermissions[1] == pkg.applicationInfo.uid
2422 || !Process.supportsProcesses()) {
2423 pkg.applicationInfo.dataDir = dataPath.getPath();
2424 } else {
2425 boolean recovered = false;
2426 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2427 // If this is a system app, we can at least delete its
2428 // current data so the application will still work.
2429 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002430 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 if(ret >= 0) {
2432 // Old data gone!
2433 String msg = "System package " + pkg.packageName
2434 + " has changed from uid: "
2435 + mOutPermissions[1] + " to "
2436 + pkg.applicationInfo.uid + "; old data erased";
2437 reportSettingsProblem(Log.WARN, msg);
2438 recovered = true;
2439
2440 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002441 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 pkg.applicationInfo.uid);
2443 if (ret == -1) {
2444 // Ack should not happen!
2445 msg = "System package " + pkg.packageName
2446 + " could not have data directory re-created after delete.";
2447 reportSettingsProblem(Log.WARN, msg);
2448 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2449 return null;
2450 }
2451 }
2452 }
2453 if (!recovered) {
2454 mHasSystemUidErrors = true;
2455 }
2456 }
2457 if (!recovered) {
2458 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2459 + pkg.applicationInfo.uid + "/fs_"
2460 + mOutPermissions[1];
2461 String msg = "Package " + pkg.packageName
2462 + " has mismatched uid: "
2463 + mOutPermissions[1] + " on disk, "
2464 + pkg.applicationInfo.uid + " in settings";
2465 synchronized (mPackages) {
2466 if (!mReportedUidError) {
2467 mReportedUidError = true;
2468 msg = msg + "; read messages:\n"
2469 + mSettings.getReadMessagesLP();
2470 }
2471 reportSettingsProblem(Log.ERROR, msg);
2472 }
2473 }
2474 }
2475 pkg.applicationInfo.dataDir = dataPath.getPath();
2476 } else {
2477 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2478 Log.v(TAG, "Want this data dir: " + dataPath);
2479 //invoke installer to do the actual installation
2480 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002481 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 pkg.applicationInfo.uid);
2483 if(ret < 0) {
2484 // Error from installer
2485 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2486 return null;
2487 }
2488 } else {
2489 dataPath.mkdirs();
2490 if (dataPath.exists()) {
2491 FileUtils.setPermissions(
2492 dataPath.toString(),
2493 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2494 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2495 }
2496 }
2497 if (dataPath.exists()) {
2498 pkg.applicationInfo.dataDir = dataPath.getPath();
2499 } else {
2500 Log.w(TAG, "Unable to create data directory: " + dataPath);
2501 pkg.applicationInfo.dataDir = null;
2502 }
2503 }
2504 }
2505
2506 // Perform shared library installation and dex validation and
2507 // optimization, if this is not a system app.
2508 if (mInstaller != null) {
2509 String path = scanFile.getPath();
2510 if (scanFileNewer) {
2511 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002512 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2513 if (err != PackageManager.INSTALL_SUCCEEDED) {
2514 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 return null;
2516 }
2517 }
2518
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002519 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2520 pkg.mScanPath = path;
2521
2522 if ((scanMode&SCAN_NO_DEX) == 0) {
2523 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2525 return null;
2526 }
2527 }
2528 }
2529
2530 if (mFactoryTest && pkg.requestedPermissions.contains(
2531 android.Manifest.permission.FACTORY_TEST)) {
2532 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2533 }
2534
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002535 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002536 if ((scanMode&SCAN_MONITOR) != 0) {
2537 pkg.mPath = destCodeFile.getAbsolutePath();
2538 mAppDirs.put(pkg.mPath, pkg);
2539 }
2540
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002541 // Request the ActivityManager to kill the process(only for existing packages)
2542 // so that we do not end up in a confused state while the user is still using the older
2543 // version of the application while the new one gets installed.
2544 IActivityManager am = ActivityManagerNative.getDefault();
2545 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2546 try {
2547 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2548 pkg.applicationInfo.uid);
2549 } catch (RemoteException e) {
2550 }
2551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002554 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002556 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 int N = pkg.providers.size();
2558 StringBuilder r = null;
2559 int i;
2560 for (i=0; i<N; i++) {
2561 PackageParser.Provider p = pkg.providers.get(i);
2562 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2563 p.info.processName, pkg.applicationInfo.uid);
2564 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2565 p.info.name), p);
2566 p.syncable = p.info.isSyncable;
2567 String names[] = p.info.authority.split(";");
2568 p.info.authority = null;
2569 for (int j = 0; j < names.length; j++) {
2570 if (j == 1 && p.syncable) {
2571 // We only want the first authority for a provider to possibly be
2572 // syncable, so if we already added this provider using a different
2573 // authority clear the syncable flag. We copy the provider before
2574 // changing it because the mProviders object contains a reference
2575 // to a provider that we don't want to change.
2576 // Only do this for the second authority since the resulting provider
2577 // object can be the same for all future authorities for this provider.
2578 p = new PackageParser.Provider(p);
2579 p.syncable = false;
2580 }
2581 if (!mProviders.containsKey(names[j])) {
2582 mProviders.put(names[j], p);
2583 if (p.info.authority == null) {
2584 p.info.authority = names[j];
2585 } else {
2586 p.info.authority = p.info.authority + ";" + names[j];
2587 }
2588 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2589 Log.d(TAG, "Registered content provider: " + names[j] +
2590 ", className = " + p.info.name +
2591 ", isSyncable = " + p.info.isSyncable);
2592 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002593 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 Log.w(TAG, "Skipping provider name " + names[j] +
2595 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002596 "): name already used by "
2597 + ((other != null && other.component != null)
2598 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 }
2600 }
2601 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2602 if (r == null) {
2603 r = new StringBuilder(256);
2604 } else {
2605 r.append(' ');
2606 }
2607 r.append(p.info.name);
2608 }
2609 }
2610 if (r != null) {
2611 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2612 }
2613
2614 N = pkg.services.size();
2615 r = null;
2616 for (i=0; i<N; i++) {
2617 PackageParser.Service s = pkg.services.get(i);
2618 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2619 s.info.processName, pkg.applicationInfo.uid);
2620 mServices.addService(s);
2621 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2622 if (r == null) {
2623 r = new StringBuilder(256);
2624 } else {
2625 r.append(' ');
2626 }
2627 r.append(s.info.name);
2628 }
2629 }
2630 if (r != null) {
2631 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2632 }
2633
2634 N = pkg.receivers.size();
2635 r = null;
2636 for (i=0; i<N; i++) {
2637 PackageParser.Activity a = pkg.receivers.get(i);
2638 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2639 a.info.processName, pkg.applicationInfo.uid);
2640 mReceivers.addActivity(a, "receiver");
2641 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2642 if (r == null) {
2643 r = new StringBuilder(256);
2644 } else {
2645 r.append(' ');
2646 }
2647 r.append(a.info.name);
2648 }
2649 }
2650 if (r != null) {
2651 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2652 }
2653
2654 N = pkg.activities.size();
2655 r = null;
2656 for (i=0; i<N; i++) {
2657 PackageParser.Activity a = pkg.activities.get(i);
2658 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2659 a.info.processName, pkg.applicationInfo.uid);
2660 mActivities.addActivity(a, "activity");
2661 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2662 if (r == null) {
2663 r = new StringBuilder(256);
2664 } else {
2665 r.append(' ');
2666 }
2667 r.append(a.info.name);
2668 }
2669 }
2670 if (r != null) {
2671 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2672 }
2673
2674 N = pkg.permissionGroups.size();
2675 r = null;
2676 for (i=0; i<N; i++) {
2677 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2678 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2679 if (cur == null) {
2680 mPermissionGroups.put(pg.info.name, pg);
2681 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2682 if (r == null) {
2683 r = new StringBuilder(256);
2684 } else {
2685 r.append(' ');
2686 }
2687 r.append(pg.info.name);
2688 }
2689 } else {
2690 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2691 + pg.info.packageName + " ignored: original from "
2692 + cur.info.packageName);
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("DUP:");
2700 r.append(pg.info.name);
2701 }
2702 }
2703 }
2704 if (r != null) {
2705 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2706 }
2707
2708 N = pkg.permissions.size();
2709 r = null;
2710 for (i=0; i<N; i++) {
2711 PackageParser.Permission p = pkg.permissions.get(i);
2712 HashMap<String, BasePermission> permissionMap =
2713 p.tree ? mSettings.mPermissionTrees
2714 : mSettings.mPermissions;
2715 p.group = mPermissionGroups.get(p.info.group);
2716 if (p.info.group == null || p.group != null) {
2717 BasePermission bp = permissionMap.get(p.info.name);
2718 if (bp == null) {
2719 bp = new BasePermission(p.info.name, p.info.packageName,
2720 BasePermission.TYPE_NORMAL);
2721 permissionMap.put(p.info.name, bp);
2722 }
2723 if (bp.perm == null) {
2724 if (bp.sourcePackage == null
2725 || bp.sourcePackage.equals(p.info.packageName)) {
2726 BasePermission tree = findPermissionTreeLP(p.info.name);
2727 if (tree == null
2728 || tree.sourcePackage.equals(p.info.packageName)) {
2729 bp.perm = p;
2730 bp.uid = pkg.applicationInfo.uid;
2731 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2732 if (r == null) {
2733 r = new StringBuilder(256);
2734 } else {
2735 r.append(' ');
2736 }
2737 r.append(p.info.name);
2738 }
2739 } else {
2740 Log.w(TAG, "Permission " + p.info.name + " from package "
2741 + p.info.packageName + " ignored: base tree "
2742 + tree.name + " is from package "
2743 + tree.sourcePackage);
2744 }
2745 } else {
2746 Log.w(TAG, "Permission " + p.info.name + " from package "
2747 + p.info.packageName + " ignored: original from "
2748 + bp.sourcePackage);
2749 }
2750 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2751 if (r == null) {
2752 r = new StringBuilder(256);
2753 } else {
2754 r.append(' ');
2755 }
2756 r.append("DUP:");
2757 r.append(p.info.name);
2758 }
2759 } else {
2760 Log.w(TAG, "Permission " + p.info.name + " from package "
2761 + p.info.packageName + " ignored: no group "
2762 + p.group);
2763 }
2764 }
2765 if (r != null) {
2766 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2767 }
2768
2769 N = pkg.instrumentation.size();
2770 r = null;
2771 for (i=0; i<N; i++) {
2772 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2773 a.info.packageName = pkg.applicationInfo.packageName;
2774 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2775 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2776 a.info.dataDir = pkg.applicationInfo.dataDir;
2777 mInstrumentation.put(a.component, a);
2778 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2779 if (r == null) {
2780 r = new StringBuilder(256);
2781 } else {
2782 r.append(' ');
2783 }
2784 r.append(a.info.name);
2785 }
2786 }
2787 if (r != null) {
2788 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2789 }
2790
Dianne Hackborn854060af2009-07-09 18:14:31 -07002791 if (pkg.protectedBroadcasts != null) {
2792 N = pkg.protectedBroadcasts.size();
2793 for (i=0; i<N; i++) {
2794 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2795 }
2796 }
2797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798 pkgSetting.setTimeStamp(scanFileTime);
2799 }
2800
2801 return pkg;
2802 }
2803
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002804 // The following constants are returned by cachePackageSharedLibsForAbiLI
2805 // to indicate if native shared libraries were found in the package.
2806 // Values are:
2807 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2808 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2809 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2810 // in package (and not installed)
2811 //
2812 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2813 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2814 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002816 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2817 // and automatically copy them to /data/data/<appname>/lib if present.
2818 //
2819 // NOTE: this method may throw an IOException if the library cannot
2820 // be copied to its final destination, e.g. if there isn't enough
2821 // room left on the data partition, or a ZipException if the package
2822 // file is malformed.
2823 //
2824 private int cachePackageSharedLibsForAbiLI( PackageParser.Package pkg,
2825 File dataPath, File scanFile, String cpuAbi)
2826 throws IOException, ZipException {
2827 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2828 final String apkLib = "lib/";
2829 final int apkLibLen = apkLib.length();
2830 final int cpuAbiLen = cpuAbi.length();
2831 final String libPrefix = "lib";
2832 final int libPrefixLen = libPrefix.length();
2833 final String libSuffix = ".so";
2834 final int libSuffixLen = libSuffix.length();
2835 boolean hasNativeLibraries = false;
2836 boolean installedNativeLibraries = false;
2837
2838 // the minimum length of a valid native shared library of the form
2839 // lib/<something>/lib<name>.so.
2840 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2841
2842 ZipFile zipFile = new ZipFile(scanFile);
2843 Enumeration<ZipEntry> entries =
2844 (Enumeration<ZipEntry>) zipFile.entries();
2845
2846 while (entries.hasMoreElements()) {
2847 ZipEntry entry = entries.nextElement();
2848 // skip directories
2849 if (entry.isDirectory()) {
2850 continue;
2851 }
2852 String entryName = entry.getName();
2853
2854 // check that the entry looks like lib/<something>/lib<name>.so
2855 // here, but don't check the ABI just yet.
2856 //
2857 // - must be sufficiently long
2858 // - must end with libSuffix, i.e. ".so"
2859 // - must start with apkLib, i.e. "lib/"
2860 if (entryName.length() < minEntryLen ||
2861 !entryName.endsWith(libSuffix) ||
2862 !entryName.startsWith(apkLib) ) {
2863 continue;
2864 }
2865
2866 // file name must start with libPrefix, i.e. "lib"
2867 int lastSlash = entryName.lastIndexOf('/');
2868
2869 if (lastSlash < 0 ||
2870 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2871 continue;
2872 }
2873
2874 hasNativeLibraries = true;
2875
2876 // check the cpuAbi now, between lib/ and /lib<name>.so
2877 //
2878 if (lastSlash != apkLibLen + cpuAbiLen ||
2879 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
2880 continue;
2881
2882 // extract the library file name, ensure it doesn't contain
2883 // weird characters. we're guaranteed here that it doesn't contain
2884 // a directory separator though.
2885 String libFileName = entryName.substring(lastSlash+1);
2886 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
2887 continue;
2888 }
2889
2890 installedNativeLibraries = true;
2891
2892 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2893 File.separator + libFileName;
2894 File sharedLibraryFile = new File(sharedLibraryFilePath);
2895 if (! sharedLibraryFile.exists() ||
2896 sharedLibraryFile.length() != entry.getSize() ||
2897 sharedLibraryFile.lastModified() != entry.getTime()) {
2898 if (Config.LOGD) {
2899 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002901 if (mInstaller == null) {
2902 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002903 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002904 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2905 sharedLibraryFile);
2906 }
2907 }
2908 if (!hasNativeLibraries)
2909 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
2910
2911 if (!installedNativeLibraries)
2912 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
2913
2914 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
2915 }
2916
2917 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
2918 // and copy them to /data/data/<appname>/lib.
2919 //
2920 // This function will first try the main CPU ABI defined by Build.CPU_ABI
2921 // (which corresponds to ro.product.cpu.abi), and also try an alternate
2922 // one if ro.product.cpu.abi2 is defined.
2923 //
2924 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2925 File dataPath, File scanFile) {
2926 final String cpuAbi = Build.CPU_ABI;
2927 try {
2928 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
2929
2930 // some architectures are capable of supporting several CPU ABIs
2931 // for example, 'armeabi-v7a' also supports 'armeabi' native code
2932 // this is indicated by the definition of the ro.product.cpu.abi2
2933 // system property.
2934 //
2935 // only scan the package twice in case of ABI mismatch
2936 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2937 String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
2938 if (cpuAbi2 != null) {
2939 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002941
2942 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2943 Log.w(TAG,"Native ABI mismatch from package file");
2944 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 }
2946 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002947 } catch (ZipException e) {
2948 Log.w(TAG, "Failed to extract data from package file", e);
2949 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002951 Log.w(TAG, "Failed to cache package shared libs", e);
2952 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002954 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 }
2956
2957 private void cacheSharedLibLI(PackageParser.Package pkg,
2958 ZipFile zipFile, ZipEntry entry,
2959 File sharedLibraryDir,
2960 File sharedLibraryFile) throws IOException {
2961 InputStream inputStream = zipFile.getInputStream(entry);
2962 try {
2963 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2964 String tempFilePath = tempFile.getPath();
2965 // XXX package manager can't change owner, so the lib files for
2966 // now need to be left as world readable and owned by the system.
2967 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2968 ! tempFile.setLastModified(entry.getTime()) ||
2969 FileUtils.setPermissions(tempFilePath,
2970 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2971 |FileUtils.S_IROTH, -1, -1) != 0 ||
2972 ! tempFile.renameTo(sharedLibraryFile)) {
2973 // Failed to properly write file.
2974 tempFile.delete();
2975 throw new IOException("Couldn't create cached shared lib "
2976 + sharedLibraryFile + " in " + sharedLibraryDir);
2977 }
2978 } finally {
2979 inputStream.close();
2980 }
2981 }
2982
2983 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2984 if (chatty && Config.LOGD) Log.d(
2985 TAG, "Removing package " + pkg.applicationInfo.packageName );
2986
2987 synchronized (mPackages) {
2988 if (pkg.mPreferredOrder > 0) {
2989 mSettings.mPreferredPackages.remove(pkg);
2990 pkg.mPreferredOrder = 0;
2991 updatePreferredIndicesLP();
2992 }
2993
2994 clearPackagePreferredActivitiesLP(pkg.packageName);
2995
2996 mPackages.remove(pkg.applicationInfo.packageName);
2997 if (pkg.mPath != null) {
2998 mAppDirs.remove(pkg.mPath);
2999 }
3000
3001 PackageSetting ps = (PackageSetting)pkg.mExtras;
3002 if (ps != null && ps.sharedUser != null) {
3003 // XXX don't do this until the data is removed.
3004 if (false) {
3005 ps.sharedUser.packages.remove(ps);
3006 if (ps.sharedUser.packages.size() == 0) {
3007 // Remove.
3008 }
3009 }
3010 }
3011
3012 int N = pkg.providers.size();
3013 StringBuilder r = null;
3014 int i;
3015 for (i=0; i<N; i++) {
3016 PackageParser.Provider p = pkg.providers.get(i);
3017 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3018 p.info.name));
3019 if (p.info.authority == null) {
3020
3021 /* The is another ContentProvider with this authority when
3022 * this app was installed so this authority is null,
3023 * Ignore it as we don't have to unregister the provider.
3024 */
3025 continue;
3026 }
3027 String names[] = p.info.authority.split(";");
3028 for (int j = 0; j < names.length; j++) {
3029 if (mProviders.get(names[j]) == p) {
3030 mProviders.remove(names[j]);
3031 if (chatty && Config.LOGD) Log.d(
3032 TAG, "Unregistered content provider: " + names[j] +
3033 ", className = " + p.info.name +
3034 ", isSyncable = " + p.info.isSyncable);
3035 }
3036 }
3037 if (chatty) {
3038 if (r == null) {
3039 r = new StringBuilder(256);
3040 } else {
3041 r.append(' ');
3042 }
3043 r.append(p.info.name);
3044 }
3045 }
3046 if (r != null) {
3047 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3048 }
3049
3050 N = pkg.services.size();
3051 r = null;
3052 for (i=0; i<N; i++) {
3053 PackageParser.Service s = pkg.services.get(i);
3054 mServices.removeService(s);
3055 if (chatty) {
3056 if (r == null) {
3057 r = new StringBuilder(256);
3058 } else {
3059 r.append(' ');
3060 }
3061 r.append(s.info.name);
3062 }
3063 }
3064 if (r != null) {
3065 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3066 }
3067
3068 N = pkg.receivers.size();
3069 r = null;
3070 for (i=0; i<N; i++) {
3071 PackageParser.Activity a = pkg.receivers.get(i);
3072 mReceivers.removeActivity(a, "receiver");
3073 if (chatty) {
3074 if (r == null) {
3075 r = new StringBuilder(256);
3076 } else {
3077 r.append(' ');
3078 }
3079 r.append(a.info.name);
3080 }
3081 }
3082 if (r != null) {
3083 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3084 }
3085
3086 N = pkg.activities.size();
3087 r = null;
3088 for (i=0; i<N; i++) {
3089 PackageParser.Activity a = pkg.activities.get(i);
3090 mActivities.removeActivity(a, "activity");
3091 if (chatty) {
3092 if (r == null) {
3093 r = new StringBuilder(256);
3094 } else {
3095 r.append(' ');
3096 }
3097 r.append(a.info.name);
3098 }
3099 }
3100 if (r != null) {
3101 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3102 }
3103
3104 N = pkg.permissions.size();
3105 r = null;
3106 for (i=0; i<N; i++) {
3107 PackageParser.Permission p = pkg.permissions.get(i);
3108 boolean tree = false;
3109 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3110 if (bp == null) {
3111 tree = true;
3112 bp = mSettings.mPermissionTrees.get(p.info.name);
3113 }
3114 if (bp != null && bp.perm == p) {
3115 if (bp.type != BasePermission.TYPE_BUILTIN) {
3116 if (tree) {
3117 mSettings.mPermissionTrees.remove(p.info.name);
3118 } else {
3119 mSettings.mPermissions.remove(p.info.name);
3120 }
3121 } else {
3122 bp.perm = null;
3123 }
3124 if (chatty) {
3125 if (r == null) {
3126 r = new StringBuilder(256);
3127 } else {
3128 r.append(' ');
3129 }
3130 r.append(p.info.name);
3131 }
3132 }
3133 }
3134 if (r != null) {
3135 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3136 }
3137
3138 N = pkg.instrumentation.size();
3139 r = null;
3140 for (i=0; i<N; i++) {
3141 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3142 mInstrumentation.remove(a.component);
3143 if (chatty) {
3144 if (r == null) {
3145 r = new StringBuilder(256);
3146 } else {
3147 r.append(' ');
3148 }
3149 r.append(a.info.name);
3150 }
3151 }
3152 if (r != null) {
3153 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3154 }
3155 }
3156 }
3157
3158 private static final boolean isPackageFilename(String name) {
3159 return name != null && name.endsWith(".apk");
3160 }
3161
3162 private void updatePermissionsLP() {
3163 // Make sure there are no dangling permission trees.
3164 Iterator<BasePermission> it = mSettings.mPermissionTrees
3165 .values().iterator();
3166 while (it.hasNext()) {
3167 BasePermission bp = it.next();
3168 if (bp.perm == null) {
3169 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3170 + " from package " + bp.sourcePackage);
3171 it.remove();
3172 }
3173 }
3174
3175 // Make sure all dynamic permissions have been assigned to a package,
3176 // and make sure there are no dangling permissions.
3177 it = mSettings.mPermissions.values().iterator();
3178 while (it.hasNext()) {
3179 BasePermission bp = it.next();
3180 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3181 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3182 + bp.name + " pkg=" + bp.sourcePackage
3183 + " info=" + bp.pendingInfo);
3184 if (bp.perm == null && bp.pendingInfo != null) {
3185 BasePermission tree = findPermissionTreeLP(bp.name);
3186 if (tree != null) {
3187 bp.perm = new PackageParser.Permission(tree.perm.owner,
3188 new PermissionInfo(bp.pendingInfo));
3189 bp.perm.info.packageName = tree.perm.info.packageName;
3190 bp.perm.info.name = bp.name;
3191 bp.uid = tree.uid;
3192 }
3193 }
3194 }
3195 if (bp.perm == null) {
3196 Log.w(TAG, "Removing dangling permission: " + bp.name
3197 + " from package " + bp.sourcePackage);
3198 it.remove();
3199 }
3200 }
3201
3202 // Now update the permissions for all packages, in particular
3203 // replace the granted permissions of the system packages.
3204 for (PackageParser.Package pkg : mPackages.values()) {
3205 grantPermissionsLP(pkg, false);
3206 }
3207 }
3208
3209 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3210 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3211 if (ps == null) {
3212 return;
3213 }
3214 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3215 boolean addedPermission = false;
3216
3217 if (replace) {
3218 ps.permissionsFixed = false;
3219 if (gp == ps) {
3220 gp.grantedPermissions.clear();
3221 gp.gids = mGlobalGids;
3222 }
3223 }
3224
3225 if (gp.gids == null) {
3226 gp.gids = mGlobalGids;
3227 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07003228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 final int N = pkg.requestedPermissions.size();
3230 for (int i=0; i<N; i++) {
3231 String name = pkg.requestedPermissions.get(i);
3232 BasePermission bp = mSettings.mPermissions.get(name);
3233 PackageParser.Permission p = bp != null ? bp.perm : null;
3234 if (false) {
3235 if (gp != ps) {
3236 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3237 + ": " + p);
3238 }
3239 }
3240 if (p != null) {
3241 final String perm = p.info.name;
3242 boolean allowed;
3243 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3244 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3245 allowed = true;
3246 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3247 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003248 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003250 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 == PackageManager.SIGNATURE_MATCH);
3252 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3253 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3254 // For updated system applications, the signatureOrSystem permission
3255 // is granted only if it had been defined by the original application.
3256 if ((pkg.applicationInfo.flags
3257 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3258 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3259 if(sysPs.grantedPermissions.contains(perm)) {
3260 allowed = true;
3261 } else {
3262 allowed = false;
3263 }
3264 } else {
3265 allowed = true;
3266 }
3267 }
3268 }
3269 } else {
3270 allowed = false;
3271 }
3272 if (false) {
3273 if (gp != ps) {
3274 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3275 }
3276 }
3277 if (allowed) {
3278 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3279 && ps.permissionsFixed) {
3280 // If this is an existing, non-system package, then
3281 // we can't add any new permissions to it.
3282 if (!gp.loadedPermissions.contains(perm)) {
3283 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003284 // Except... if this is a permission that was added
3285 // to the platform (note: need to only do this when
3286 // updating the platform).
3287 final int NP = PackageParser.NEW_PERMISSIONS.length;
3288 for (int ip=0; ip<NP; ip++) {
3289 final PackageParser.NewPermissionInfo npi
3290 = PackageParser.NEW_PERMISSIONS[ip];
3291 if (npi.name.equals(perm)
3292 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3293 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003294 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003295 + pkg.packageName);
3296 break;
3297 }
3298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 }
3300 }
3301 if (allowed) {
3302 if (!gp.grantedPermissions.contains(perm)) {
3303 addedPermission = true;
3304 gp.grantedPermissions.add(perm);
3305 gp.gids = appendInts(gp.gids, bp.gids);
3306 }
3307 } else {
3308 Log.w(TAG, "Not granting permission " + perm
3309 + " to package " + pkg.packageName
3310 + " because it was previously installed without");
3311 }
3312 } else {
3313 Log.w(TAG, "Not granting permission " + perm
3314 + " to package " + pkg.packageName
3315 + " (protectionLevel=" + p.info.protectionLevel
3316 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3317 + ")");
3318 }
3319 } else {
3320 Log.w(TAG, "Unknown permission " + name
3321 + " in package " + pkg.packageName);
3322 }
3323 }
3324
3325 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003326 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3327 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 // This is the first that we have heard about this package, so the
3329 // permissions we have now selected are fixed until explicitly
3330 // changed.
3331 ps.permissionsFixed = true;
3332 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3333 }
3334 }
3335
3336 private final class ActivityIntentResolver
3337 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003338 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003340 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 }
3342
Mihai Preda074edef2009-05-18 17:13:31 +02003343 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003345 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3347 }
3348
Mihai Predaeae850c2009-05-13 10:13:48 +02003349 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3350 ArrayList<PackageParser.Activity> packageActivities) {
3351 if (packageActivities == null) {
3352 return null;
3353 }
3354 mFlags = flags;
3355 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3356 int N = packageActivities.size();
3357 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3358 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003359
3360 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003361 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003362 intentFilters = packageActivities.get(i).intents;
3363 if (intentFilters != null && intentFilters.size() > 0) {
3364 listCut.add(intentFilters);
3365 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003366 }
3367 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3368 }
3369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 public final void addActivity(PackageParser.Activity a, String type) {
3371 mActivities.put(a.component, a);
3372 if (SHOW_INFO || Config.LOGV) Log.v(
3373 TAG, " " + type + " " +
3374 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3375 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3376 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003377 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3379 if (SHOW_INFO || Config.LOGV) {
3380 Log.v(TAG, " IntentFilter:");
3381 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3382 }
3383 if (!intent.debugCheck()) {
3384 Log.w(TAG, "==> For Activity " + a.info.name);
3385 }
3386 addFilter(intent);
3387 }
3388 }
3389
3390 public final void removeActivity(PackageParser.Activity a, String type) {
3391 mActivities.remove(a.component);
3392 if (SHOW_INFO || Config.LOGV) Log.v(
3393 TAG, " " + type + " " +
3394 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3395 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3396 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003397 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3399 if (SHOW_INFO || Config.LOGV) {
3400 Log.v(TAG, " IntentFilter:");
3401 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3402 }
3403 removeFilter(intent);
3404 }
3405 }
3406
3407 @Override
3408 protected boolean allowFilterResult(
3409 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3410 ActivityInfo filterAi = filter.activity.info;
3411 for (int i=dest.size()-1; i>=0; i--) {
3412 ActivityInfo destAi = dest.get(i).activityInfo;
3413 if (destAi.name == filterAi.name
3414 && destAi.packageName == filterAi.packageName) {
3415 return false;
3416 }
3417 }
3418 return true;
3419 }
3420
3421 @Override
3422 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3423 int match) {
3424 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3425 return null;
3426 }
3427 final PackageParser.Activity activity = info.activity;
3428 if (mSafeMode && (activity.info.applicationInfo.flags
3429 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3430 return null;
3431 }
3432 final ResolveInfo res = new ResolveInfo();
3433 res.activityInfo = PackageParser.generateActivityInfo(activity,
3434 mFlags);
3435 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3436 res.filter = info;
3437 }
3438 res.priority = info.getPriority();
3439 res.preferredOrder = activity.owner.mPreferredOrder;
3440 //System.out.println("Result: " + res.activityInfo.className +
3441 // " = " + res.priority);
3442 res.match = match;
3443 res.isDefault = info.hasDefault;
3444 res.labelRes = info.labelRes;
3445 res.nonLocalizedLabel = info.nonLocalizedLabel;
3446 res.icon = info.icon;
3447 return res;
3448 }
3449
3450 @Override
3451 protected void sortResults(List<ResolveInfo> results) {
3452 Collections.sort(results, mResolvePrioritySorter);
3453 }
3454
3455 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003456 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003458 out.print(prefix); out.print(
3459 Integer.toHexString(System.identityHashCode(filter.activity)));
3460 out.print(' ');
3461 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003462 }
3463
3464// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3465// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3466// final List<ResolveInfo> retList = Lists.newArrayList();
3467// while (i.hasNext()) {
3468// final ResolveInfo resolveInfo = i.next();
3469// if (isEnabledLP(resolveInfo.activityInfo)) {
3470// retList.add(resolveInfo);
3471// }
3472// }
3473// return retList;
3474// }
3475
3476 // Keys are String (activity class name), values are Activity.
3477 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3478 = new HashMap<ComponentName, PackageParser.Activity>();
3479 private int mFlags;
3480 }
3481
3482 private final class ServiceIntentResolver
3483 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003484 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003486 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 }
3488
Mihai Preda074edef2009-05-18 17:13:31 +02003489 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003491 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3493 }
3494
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003495 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3496 ArrayList<PackageParser.Service> packageServices) {
3497 if (packageServices == null) {
3498 return null;
3499 }
3500 mFlags = flags;
3501 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3502 int N = packageServices.size();
3503 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3504 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3505
3506 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3507 for (int i = 0; i < N; ++i) {
3508 intentFilters = packageServices.get(i).intents;
3509 if (intentFilters != null && intentFilters.size() > 0) {
3510 listCut.add(intentFilters);
3511 }
3512 }
3513 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3514 }
3515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 public final void addService(PackageParser.Service s) {
3517 mServices.put(s.component, s);
3518 if (SHOW_INFO || Config.LOGV) Log.v(
3519 TAG, " " + (s.info.nonLocalizedLabel != null
3520 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3521 if (SHOW_INFO || Config.LOGV) Log.v(
3522 TAG, " Class=" + s.info.name);
3523 int NI = s.intents.size();
3524 int j;
3525 for (j=0; j<NI; j++) {
3526 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3527 if (SHOW_INFO || Config.LOGV) {
3528 Log.v(TAG, " IntentFilter:");
3529 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3530 }
3531 if (!intent.debugCheck()) {
3532 Log.w(TAG, "==> For Service " + s.info.name);
3533 }
3534 addFilter(intent);
3535 }
3536 }
3537
3538 public final void removeService(PackageParser.Service s) {
3539 mServices.remove(s.component);
3540 if (SHOW_INFO || Config.LOGV) Log.v(
3541 TAG, " " + (s.info.nonLocalizedLabel != null
3542 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3543 if (SHOW_INFO || Config.LOGV) Log.v(
3544 TAG, " Class=" + s.info.name);
3545 int NI = s.intents.size();
3546 int j;
3547 for (j=0; j<NI; j++) {
3548 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3549 if (SHOW_INFO || Config.LOGV) {
3550 Log.v(TAG, " IntentFilter:");
3551 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3552 }
3553 removeFilter(intent);
3554 }
3555 }
3556
3557 @Override
3558 protected boolean allowFilterResult(
3559 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3560 ServiceInfo filterSi = filter.service.info;
3561 for (int i=dest.size()-1; i>=0; i--) {
3562 ServiceInfo destAi = dest.get(i).serviceInfo;
3563 if (destAi.name == filterSi.name
3564 && destAi.packageName == filterSi.packageName) {
3565 return false;
3566 }
3567 }
3568 return true;
3569 }
3570
3571 @Override
3572 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3573 int match) {
3574 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3575 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3576 return null;
3577 }
3578 final PackageParser.Service service = info.service;
3579 if (mSafeMode && (service.info.applicationInfo.flags
3580 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3581 return null;
3582 }
3583 final ResolveInfo res = new ResolveInfo();
3584 res.serviceInfo = PackageParser.generateServiceInfo(service,
3585 mFlags);
3586 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3587 res.filter = filter;
3588 }
3589 res.priority = info.getPriority();
3590 res.preferredOrder = service.owner.mPreferredOrder;
3591 //System.out.println("Result: " + res.activityInfo.className +
3592 // " = " + res.priority);
3593 res.match = match;
3594 res.isDefault = info.hasDefault;
3595 res.labelRes = info.labelRes;
3596 res.nonLocalizedLabel = info.nonLocalizedLabel;
3597 res.icon = info.icon;
3598 return res;
3599 }
3600
3601 @Override
3602 protected void sortResults(List<ResolveInfo> results) {
3603 Collections.sort(results, mResolvePrioritySorter);
3604 }
3605
3606 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003607 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003609 out.print(prefix); out.print(
3610 Integer.toHexString(System.identityHashCode(filter.service)));
3611 out.print(' ');
3612 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 }
3614
3615// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3616// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3617// final List<ResolveInfo> retList = Lists.newArrayList();
3618// while (i.hasNext()) {
3619// final ResolveInfo resolveInfo = (ResolveInfo) i;
3620// if (isEnabledLP(resolveInfo.serviceInfo)) {
3621// retList.add(resolveInfo);
3622// }
3623// }
3624// return retList;
3625// }
3626
3627 // Keys are String (activity class name), values are Activity.
3628 private final HashMap<ComponentName, PackageParser.Service> mServices
3629 = new HashMap<ComponentName, PackageParser.Service>();
3630 private int mFlags;
3631 };
3632
3633 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3634 new Comparator<ResolveInfo>() {
3635 public int compare(ResolveInfo r1, ResolveInfo r2) {
3636 int v1 = r1.priority;
3637 int v2 = r2.priority;
3638 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3639 if (v1 != v2) {
3640 return (v1 > v2) ? -1 : 1;
3641 }
3642 v1 = r1.preferredOrder;
3643 v2 = r2.preferredOrder;
3644 if (v1 != v2) {
3645 return (v1 > v2) ? -1 : 1;
3646 }
3647 if (r1.isDefault != r2.isDefault) {
3648 return r1.isDefault ? -1 : 1;
3649 }
3650 v1 = r1.match;
3651 v2 = r2.match;
3652 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3653 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3654 }
3655 };
3656
3657 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3658 new Comparator<ProviderInfo>() {
3659 public int compare(ProviderInfo p1, ProviderInfo p2) {
3660 final int v1 = p1.initOrder;
3661 final int v2 = p2.initOrder;
3662 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3663 }
3664 };
3665
3666 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3667 IActivityManager am = ActivityManagerNative.getDefault();
3668 if (am != null) {
3669 try {
3670 final Intent intent = new Intent(action,
3671 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3672 if (extras != null) {
3673 intent.putExtras(extras);
3674 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003675 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 am.broadcastIntent(
3677 null, intent,
3678 null, null, 0, null, null, null, false, false);
3679 } catch (RemoteException ex) {
3680 }
3681 }
3682 }
3683
3684 private final class AppDirObserver extends FileObserver {
3685 public AppDirObserver(String path, int mask, boolean isrom) {
3686 super(path, mask);
3687 mRootDir = path;
3688 mIsRom = isrom;
3689 }
3690
3691 public void onEvent(int event, String path) {
3692 String removedPackage = null;
3693 int removedUid = -1;
3694 String addedPackage = null;
3695 int addedUid = -1;
3696
3697 synchronized (mInstallLock) {
3698 String fullPathStr = null;
3699 File fullPath = null;
3700 if (path != null) {
3701 fullPath = new File(mRootDir, path);
3702 fullPathStr = fullPath.getPath();
3703 }
3704
3705 if (Config.LOGV) Log.v(
3706 TAG, "File " + fullPathStr + " changed: "
3707 + Integer.toHexString(event));
3708
3709 if (!isPackageFilename(path)) {
3710 if (Config.LOGV) Log.v(
3711 TAG, "Ignoring change of non-package file: " + fullPathStr);
3712 return;
3713 }
3714
3715 if ((event&REMOVE_EVENTS) != 0) {
3716 synchronized (mInstallLock) {
3717 PackageParser.Package p = mAppDirs.get(fullPathStr);
3718 if (p != null) {
3719 removePackageLI(p, true);
3720 removedPackage = p.applicationInfo.packageName;
3721 removedUid = p.applicationInfo.uid;
3722 }
3723 }
3724 }
3725
3726 if ((event&ADD_EVENTS) != 0) {
3727 PackageParser.Package p = mAppDirs.get(fullPathStr);
3728 if (p == null) {
3729 p = scanPackageLI(fullPath, fullPath, fullPath,
3730 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3731 PackageParser.PARSE_CHATTY |
3732 PackageParser.PARSE_MUST_BE_APK,
3733 SCAN_MONITOR);
3734 if (p != null) {
3735 synchronized (mPackages) {
3736 grantPermissionsLP(p, false);
3737 }
3738 addedPackage = p.applicationInfo.packageName;
3739 addedUid = p.applicationInfo.uid;
3740 }
3741 }
3742 }
3743
3744 synchronized (mPackages) {
3745 mSettings.writeLP();
3746 }
3747 }
3748
3749 if (removedPackage != null) {
3750 Bundle extras = new Bundle(1);
3751 extras.putInt(Intent.EXTRA_UID, removedUid);
3752 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3753 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3754 }
3755 if (addedPackage != null) {
3756 Bundle extras = new Bundle(1);
3757 extras.putInt(Intent.EXTRA_UID, addedUid);
3758 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3759 }
3760 }
3761
3762 private final String mRootDir;
3763 private final boolean mIsRom;
3764 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 /* Called when a downloaded package installation has been confirmed by the user */
3767 public void installPackage(
3768 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003769 installPackage(packageURI, observer, flags, null);
3770 }
3771
3772 /* Called when a downloaded package installation has been confirmed by the user */
3773 public void installPackage(
3774 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3775 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 mContext.enforceCallingOrSelfPermission(
3777 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 // Queue up an async operation since the package installation may take a little while.
3780 mHandler.post(new Runnable() {
3781 public void run() {
3782 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003783 // Result object to be returned
3784 PackageInstalledInfo res = new PackageInstalledInfo();
3785 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3786 res.uid = -1;
3787 res.pkg = null;
3788 res.removedInfo = new PackageRemovedInfo();
3789 // Make a temporary copy of file from given packageURI
3790 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3791 if (tmpPackageFile != null) {
3792 synchronized (mInstallLock) {
3793 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 }
3796 if (observer != null) {
3797 try {
3798 observer.packageInstalled(res.name, res.returnCode);
3799 } catch (RemoteException e) {
3800 Log.i(TAG, "Observer no longer exists.");
3801 }
3802 }
3803 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3804 // call appears in the synchronized block above.
3805 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3806 res.removedInfo.sendBroadcast(false, true);
3807 Bundle extras = new Bundle(1);
3808 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003809 final boolean update = res.removedInfo.removedPackage != null;
3810 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3812 }
3813 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3814 res.pkg.applicationInfo.packageName,
3815 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003816 if (update) {
3817 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3818 res.pkg.applicationInfo.packageName,
3819 extras);
3820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 }
3822 Runtime.getRuntime().gc();
3823 }
3824 });
3825 }
3826
3827 class PackageInstalledInfo {
3828 String name;
3829 int uid;
3830 PackageParser.Package pkg;
3831 int returnCode;
3832 PackageRemovedInfo removedInfo;
3833 }
3834
3835 /*
3836 * Install a non-existing package.
3837 */
3838 private void installNewPackageLI(String pkgName,
3839 File tmpPackageFile,
3840 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003841 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003842 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08003844 boolean dataDirExists;
3845
3846 if (useEncryptedFilesystemForPackage(pkg)) {
3847 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
3848 } else {
3849 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 res.name = pkgName;
3852 synchronized(mPackages) {
3853 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3854 // Don't allow installation over an existing package with the same name.
3855 Log.w(TAG, "Attempt to re-install " + pkgName
3856 + " without first uninstalling.");
3857 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3858 return;
3859 }
3860 }
3861 if (destPackageFile.exists()) {
3862 // It's safe to do this because we know (from the above check) that the file
3863 // isn't currently used for an installed package.
3864 destPackageFile.delete();
3865 }
3866 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3867 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3868 destResourceFile, pkg, 0,
3869 SCAN_MONITOR | SCAN_FORCE_DEX
3870 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003871 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3872 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 if (newPackage == null) {
3874 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3875 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3876 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3877 }
3878 } else {
3879 updateSettingsLI(pkgName, tmpPackageFile,
3880 destFilePath, destPackageFile,
3881 destResourceFile, pkg,
3882 newPackage,
3883 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003884 forwardLocked,
3885 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 res);
3887 // delete the partially installed application. the data directory will have to be
3888 // restored if it was already existing
3889 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3890 // remove package from internal structures. Note that we want deletePackageX to
3891 // delete the package data and cache directories that it created in
3892 // scanPackageLocked, unless those directories existed before we even tried to
3893 // install.
3894 deletePackageLI(
3895 pkgName, true,
3896 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3897 res.removedInfo);
3898 }
3899 }
3900 }
3901
3902 private void replacePackageLI(String pkgName,
3903 File tmpPackageFile,
3904 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003905 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003906 String installerPackageName, PackageInstalledInfo res) {
3907
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003908 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003909 // First find the old package info and check signatures
3910 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003911 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003912 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3913 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3915 return;
3916 }
3917 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003918 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003920 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003922 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003923 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003925 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003926 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003927 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
3929 }
3930
3931 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3932 File tmpPackageFile,
3933 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003934 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003935 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 PackageParser.Package newPackage = null;
3937 String pkgName = deletedPackage.packageName;
3938 boolean deletedPkg = true;
3939 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003940
3941 String oldInstallerPackageName = null;
3942 synchronized (mPackages) {
3943 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3944 }
3945
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003946 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 // First delete the existing package while retaining the data directory
3948 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3949 res.removedInfo)) {
3950 // If the existing package was'nt successfully deleted
3951 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3952 deletedPkg = false;
3953 } else {
3954 // Successfully deleted the old package. Now proceed with re-installation
3955 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3956 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3957 destResourceFile, pkg, parseFlags,
3958 SCAN_MONITOR | SCAN_FORCE_DEX
3959 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003960 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3961 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 if (newPackage == null) {
3963 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3964 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3965 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3966 }
3967 } else {
3968 updateSettingsLI(pkgName, tmpPackageFile,
3969 destFilePath, destPackageFile,
3970 destResourceFile, pkg,
3971 newPackage,
3972 true,
3973 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003974 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 res);
3976 updatedSettings = true;
3977 }
3978 }
3979
3980 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3981 // If we deleted an exisiting package, the old source and resource files that we
3982 // were keeping around in case we needed them (see below) can now be deleted
3983 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3984 final ApplicationInfo installedPackageAppInfo =
3985 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003986 deletePackageResourcesLI(pkgName,
3987 !deletedPackageAppInfo.sourceDir
3988 .equals(installedPackageAppInfo.sourceDir)
3989 ? deletedPackageAppInfo.sourceDir : null,
3990 !deletedPackageAppInfo.publicSourceDir
3991 .equals(installedPackageAppInfo.publicSourceDir)
3992 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 //update signature on the new package setting
3994 //this should always succeed, since we checked the
3995 //signature earlier.
3996 synchronized(mPackages) {
3997 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3998 parseFlags, true);
3999 }
4000 } else {
4001 // remove package from internal structures. Note that we want deletePackageX to
4002 // delete the package data and cache directories that it created in
4003 // scanPackageLocked, unless those directories existed before we even tried to
4004 // install.
4005 if(updatedSettings) {
4006 deletePackageLI(
4007 pkgName, true,
4008 PackageManager.DONT_DELETE_DATA,
4009 res.removedInfo);
4010 }
4011 // Since we failed to install the new package we need to restore the old
4012 // package that we deleted.
4013 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004014 File restoreFile = new File(deletedPackage.mPath);
4015 if (restoreFile == null) {
4016 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4017 return;
4018 }
4019 File restoreTmpFile = createTempPackageFile();
4020 if (restoreTmpFile == null) {
4021 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
4022 return;
4023 }
4024 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
4025 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
4026 return;
4027 }
4028 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4029 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004031 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004033 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004034 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
4035 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4036 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 }
4039 }
4040 }
4041
4042 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
4043 File tmpPackageFile,
4044 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07004045 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02004046 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 PackageParser.Package newPackage = null;
4048 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004049 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 PackageParser.PARSE_IS_SYSTEM;
4051 String packageName = deletedPackage.packageName;
4052 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4053 if (packageName == null) {
4054 Log.w(TAG, "Attempt to delete null packageName.");
4055 return;
4056 }
4057 PackageParser.Package oldPkg;
4058 PackageSetting oldPkgSetting;
4059 synchronized (mPackages) {
4060 oldPkg = mPackages.get(packageName);
4061 oldPkgSetting = mSettings.mPackages.get(packageName);
4062 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4063 (oldPkgSetting == null)) {
4064 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4065 return;
4066 }
4067 }
4068 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4069 res.removedInfo.removedPackage = packageName;
4070 // Remove existing system package
4071 removePackageLI(oldPkg, true);
4072 synchronized (mPackages) {
4073 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4074 }
4075
4076 // Successfully disabled the old package. Now proceed with re-installation
4077 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4078 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
4079 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
4080 destResourceFile, pkg, parseFlags,
4081 SCAN_MONITOR | SCAN_FORCE_DEX
4082 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07004083 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
4084 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 if (newPackage == null) {
4086 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
4087 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4088 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4089 }
4090 } else {
4091 updateSettingsLI(packageName, tmpPackageFile,
4092 destFilePath, destPackageFile,
4093 destResourceFile, pkg,
4094 newPackage,
4095 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02004096 forwardLocked,
4097 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 res);
4099 updatedSettings = true;
4100 }
4101
4102 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4103 //update signature on the new package setting
4104 //this should always succeed, since we checked the
4105 //signature earlier.
4106 synchronized(mPackages) {
4107 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4108 parseFlags, true);
4109 }
4110 } else {
4111 // Re installation failed. Restore old information
4112 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004113 if (newPackage != null) {
4114 removePackageLI(newPackage, true);
4115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 // Add back the old system package
4117 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
4118 oldPkgSetting.resourcePath,
4119 oldPkg, parseFlags,
4120 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004121 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 // Restore the old system information in Settings
4123 synchronized(mPackages) {
4124 if(updatedSettings) {
4125 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004126 mSettings.setInstallerPackageName(packageName,
4127 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 }
4129 mSettings.writeLP();
4130 }
4131 }
4132 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 private void updateSettingsLI(String pkgName, File tmpPackageFile,
4135 String destFilePath, File destPackageFile,
4136 File destResourceFile,
4137 PackageParser.Package pkg,
4138 PackageParser.Package newPackage,
4139 boolean replacingExistingPackage,
4140 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02004141 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 synchronized (mPackages) {
4143 //write settings. the installStatus will be incomplete at this stage.
4144 //note that the new package setting would have already been
4145 //added to mPackages. It hasn't been persisted yet.
4146 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4147 mSettings.writeLP();
4148 }
4149
4150 int retCode = 0;
4151 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4152 retCode = mInstaller.movedex(tmpPackageFile.toString(),
4153 destPackageFile.toString());
4154 if (retCode != 0) {
4155 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
4156 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4157 return;
4158 }
4159 }
4160 // XXX There are probably some big issues here: upon doing
4161 // the rename, we have reached the point of no return (the
4162 // original .apk is gone!), so we can't fail. Yet... we can.
4163 if (!tmpPackageFile.renameTo(destPackageFile)) {
4164 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
4165 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4166 } else {
4167 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4168 destResourceFile,
4169 forwardLocked);
4170 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4171 return;
4172 } else {
4173 Log.d(TAG, "New package installed in " + destPackageFile);
4174 }
4175 }
4176 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4177 if (mInstaller != null) {
4178 mInstaller.rmdex(tmpPackageFile.getPath());
4179 }
4180 }
4181
4182 synchronized (mPackages) {
4183 grantPermissionsLP(newPackage, true);
4184 res.name = pkgName;
4185 res.uid = newPackage.applicationInfo.uid;
4186 res.pkg = newPackage;
4187 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004188 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4190 //to update install status
4191 mSettings.writeLP();
4192 }
4193 }
4194
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004195 private File getFwdLockedResource(String pkgName) {
4196 final String publicZipFileName = pkgName + ".zip";
4197 return new File(mAppInstallDir, publicZipFileName);
4198 }
4199
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004200 private File copyTempInstallFile(Uri pPackageURI,
4201 PackageInstalledInfo res) {
4202 File tmpPackageFile = createTempPackageFile();
4203 int retCode = PackageManager.INSTALL_SUCCEEDED;
4204 if (tmpPackageFile == null) {
4205 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4206 return null;
4207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004209 if (pPackageURI.getScheme().equals("file")) {
4210 final File srcPackageFile = new File(pPackageURI.getPath());
4211 // We copy the source package file to a temp file and then rename it to the
4212 // destination file in order to eliminate a window where the package directory
4213 // scanner notices the new package file but it's not completely copied yet.
4214 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4215 Log.e(TAG, "Couldn't copy package file to temp file.");
4216 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004218 } else if (pPackageURI.getScheme().equals("content")) {
4219 ParcelFileDescriptor fd = null;
4220 try {
4221 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4222 } catch (FileNotFoundException e) {
4223 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4224 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4225 }
4226 if (fd == null) {
4227 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4228 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4229 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 if (Config.LOGV) {
4231 Log.v(TAG, "Opened file descriptor from download service.");
4232 }
4233 ParcelFileDescriptor.AutoCloseInputStream
4234 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4235 // We copy the source package file to a temp file and then rename it to the
4236 // destination file in order to eliminate a window where the package directory
4237 // scanner notices the new package file but it's not completely copied yet.
4238 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4239 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004240 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004243 } else {
4244 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4245 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4246 }
4247
4248 res.returnCode = retCode;
4249 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4250 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4251 tmpPackageFile.delete();
4252 }
4253 return null;
4254 }
4255 return tmpPackageFile;
4256 }
4257
4258 private void installPackageLI(Uri pPackageURI,
4259 int pFlags, boolean newInstall, String installerPackageName,
4260 File tmpPackageFile, PackageInstalledInfo res) {
4261 String pkgName = null;
4262 boolean forwardLocked = false;
4263 boolean replacingExistingPackage = false;
4264 // Result object to be returned
4265 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4266
4267 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 pkgName = PackageParser.parsePackageName(
4269 tmpPackageFile.getAbsolutePath(), 0);
4270 if (pkgName == null) {
4271 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4272 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4273 break main_flow;
4274 }
4275 res.name = pkgName;
4276 //initialize some variables before installing pkg
4277 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004278 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004279 ? mDrmAppPrivateInstallDir
4280 : mAppInstallDir;
4281 final File destPackageFile = new File(destDir, pkgFileName);
4282 final String destFilePath = destPackageFile.getAbsolutePath();
4283 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004284 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004285 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 forwardLocked = true;
4287 } else {
4288 destResourceFile = destPackageFile;
4289 }
4290 // Retrieve PackageSettings and parse package
4291 int parseFlags = PackageParser.PARSE_CHATTY;
4292 parseFlags |= mDefParseFlags;
4293 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4294 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4296 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4297 if (pkg == null) {
4298 res.returnCode = pp.getParseError();
4299 break main_flow;
4300 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004301 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4302 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4303 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4304 break main_flow;
4305 }
4306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4308 res.returnCode = pp.getParseError();
4309 break main_flow;
4310 }
4311
4312 synchronized (mPackages) {
4313 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004314 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 && mPackages.containsKey(pkgName)) {
4316 replacingExistingPackage = true;
4317 }
4318 }
4319
4320 if(replacingExistingPackage) {
4321 replacePackageLI(pkgName,
4322 tmpPackageFile,
4323 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004324 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 res);
4326 } else {
4327 installNewPackageLI(pkgName,
4328 tmpPackageFile,
4329 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004330 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 res);
4332 }
4333 } finally {
4334 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4335 tmpPackageFile.delete();
4336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 }
4338 }
4339
4340 private int setPermissionsLI(String pkgName,
4341 PackageParser.Package newPackage,
4342 String destFilePath,
4343 File destResourceFile,
4344 boolean forwardLocked) {
4345 int retCode;
4346 if (forwardLocked) {
4347 try {
4348 extractPublicFiles(newPackage, destResourceFile);
4349 } catch (IOException e) {
4350 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4351 " forward-locked app.");
4352 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4353 } finally {
4354 //TODO clean up the extracted public files
4355 }
4356 if (mInstaller != null) {
4357 retCode = mInstaller.setForwardLockPerm(pkgName,
4358 newPackage.applicationInfo.uid);
4359 } else {
4360 final int filePermissions =
4361 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4362 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4363 newPackage.applicationInfo.uid);
4364 }
4365 } else {
4366 final int filePermissions =
4367 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4368 |FileUtils.S_IROTH;
4369 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4370 }
4371 if (retCode != 0) {
4372 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4373 + ". The return code was: " + retCode);
4374 }
4375 return PackageManager.INSTALL_SUCCEEDED;
4376 }
4377
4378 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4379 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4380 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4381 }
4382
4383 private void extractPublicFiles(PackageParser.Package newPackage,
4384 File publicZipFile) throws IOException {
4385 final ZipOutputStream publicZipOutStream =
4386 new ZipOutputStream(new FileOutputStream(publicZipFile));
4387 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4388
4389 // Copy manifest, resources.arsc and res directory to public zip
4390
4391 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4392 while (privateZipEntries.hasMoreElements()) {
4393 final ZipEntry zipEntry = privateZipEntries.nextElement();
4394 final String zipEntryName = zipEntry.getName();
4395 if ("AndroidManifest.xml".equals(zipEntryName)
4396 || "resources.arsc".equals(zipEntryName)
4397 || zipEntryName.startsWith("res/")) {
4398 try {
4399 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4400 } catch (IOException e) {
4401 try {
4402 publicZipOutStream.close();
4403 throw e;
4404 } finally {
4405 publicZipFile.delete();
4406 }
4407 }
4408 }
4409 }
4410
4411 publicZipOutStream.close();
4412 FileUtils.setPermissions(
4413 publicZipFile.getAbsolutePath(),
4414 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4415 -1, -1);
4416 }
4417
4418 private static void copyZipEntry(ZipEntry zipEntry,
4419 ZipFile inZipFile,
4420 ZipOutputStream outZipStream) throws IOException {
4421 byte[] buffer = new byte[4096];
4422 int num;
4423
4424 ZipEntry newEntry;
4425 if (zipEntry.getMethod() == ZipEntry.STORED) {
4426 // Preserve the STORED method of the input entry.
4427 newEntry = new ZipEntry(zipEntry);
4428 } else {
4429 // Create a new entry so that the compressed len is recomputed.
4430 newEntry = new ZipEntry(zipEntry.getName());
4431 }
4432 outZipStream.putNextEntry(newEntry);
4433
4434 InputStream data = inZipFile.getInputStream(zipEntry);
4435 while ((num = data.read(buffer)) > 0) {
4436 outZipStream.write(buffer, 0, num);
4437 }
4438 outZipStream.flush();
4439 }
4440
4441 private void deleteTempPackageFiles() {
4442 FilenameFilter filter = new FilenameFilter() {
4443 public boolean accept(File dir, String name) {
4444 return name.startsWith("vmdl") && name.endsWith(".tmp");
4445 }
4446 };
4447 String tmpFilesList[] = mAppInstallDir.list(filter);
4448 if(tmpFilesList == null) {
4449 return;
4450 }
4451 for(int i = 0; i < tmpFilesList.length; i++) {
4452 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4453 tmpFile.delete();
4454 }
4455 }
4456
4457 private File createTempPackageFile() {
4458 File tmpPackageFile;
4459 try {
4460 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4461 } catch (IOException e) {
4462 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4463 return null;
4464 }
4465 try {
4466 FileUtils.setPermissions(
4467 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4468 -1, -1);
4469 } catch (IOException e) {
4470 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4471 return null;
4472 }
4473 return tmpPackageFile;
4474 }
4475
4476 public void deletePackage(final String packageName,
4477 final IPackageDeleteObserver observer,
4478 final int flags) {
4479 mContext.enforceCallingOrSelfPermission(
4480 android.Manifest.permission.DELETE_PACKAGES, null);
4481 // Queue up an async operation since the package deletion may take a little while.
4482 mHandler.post(new Runnable() {
4483 public void run() {
4484 mHandler.removeCallbacks(this);
4485 final boolean succeded = deletePackageX(packageName, true, true, flags);
4486 if (observer != null) {
4487 try {
4488 observer.packageDeleted(succeded);
4489 } catch (RemoteException e) {
4490 Log.i(TAG, "Observer no longer exists.");
4491 } //end catch
4492 } //end if
4493 } //end run
4494 });
4495 }
4496
4497 /**
4498 * This method is an internal method that could be get invoked either
4499 * to delete an installed package or to clean up a failed installation.
4500 * After deleting an installed package, a broadcast is sent to notify any
4501 * listeners that the package has been installed. For cleaning up a failed
4502 * installation, the broadcast is not necessary since the package's
4503 * installation wouldn't have sent the initial broadcast either
4504 * The key steps in deleting a package are
4505 * deleting the package information in internal structures like mPackages,
4506 * deleting the packages base directories through installd
4507 * updating mSettings to reflect current status
4508 * persisting settings for later use
4509 * sending a broadcast if necessary
4510 */
4511
4512 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4513 boolean deleteCodeAndResources, int flags) {
4514 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004515 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516
4517 synchronized (mInstallLock) {
4518 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4519 }
4520
4521 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004522 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4523 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4524
4525 // If the removed package was a system update, the old system packaged
4526 // was re-enabled; we need to broadcast this information
4527 if (systemUpdate) {
4528 Bundle extras = new Bundle(1);
4529 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4530 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4531
4532 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4533 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 }
4536 return res;
4537 }
4538
4539 static class PackageRemovedInfo {
4540 String removedPackage;
4541 int uid = -1;
4542 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004543 boolean isRemovedPackageSystemUpdate = false;
4544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 void sendBroadcast(boolean fullRemove, boolean replacing) {
4546 Bundle extras = new Bundle(1);
4547 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4548 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4549 if (replacing) {
4550 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4551 }
4552 if (removedPackage != null) {
4553 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4554 }
4555 if (removedUid >= 0) {
4556 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4557 }
4558 }
4559 }
4560
4561 /*
4562 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4563 * flag is not set, the data directory is removed as well.
4564 * make sure this flag is set for partially installed apps. If not its meaningless to
4565 * delete a partially installed application.
4566 */
4567 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4568 int flags) {
4569 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004570 if (outInfo != null) {
4571 outInfo.removedPackage = packageName;
4572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 removePackageLI(p, true);
4574 // Retrieve object to delete permissions for shared user later on
4575 PackageSetting deletedPs;
4576 synchronized (mPackages) {
4577 deletedPs = mSettings.mPackages.get(packageName);
4578 }
4579 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004580 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004582 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 if (retCode < 0) {
4584 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4585 + packageName + ", retcode=" + retCode);
4586 // we don't consider this to be a failure of the core package deletion
4587 }
4588 } else {
4589 //for emulator
4590 PackageParser.Package pkg = mPackages.get(packageName);
4591 File dataDir = new File(pkg.applicationInfo.dataDir);
4592 dataDir.delete();
4593 }
4594 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004595 if (outInfo != null) {
4596 outInfo.removedUid = mSettings.removePackageLP(packageName);
4597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 }
4599 }
4600 synchronized (mPackages) {
4601 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4602 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004603 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 }
4605 // Save settings now
4606 mSettings.writeLP ();
4607 }
4608 }
4609
4610 /*
4611 * Tries to delete system package.
4612 */
4613 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004614 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 ApplicationInfo applicationInfo = p.applicationInfo;
4616 //applicable for non-partially installed applications only
4617 if (applicationInfo == null) {
4618 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4619 return false;
4620 }
4621 PackageSetting ps = null;
4622 // Confirm if the system package has been updated
4623 // An updated system app can be deleted. This will also have to restore
4624 // the system pkg from system partition
4625 synchronized (mPackages) {
4626 ps = mSettings.getDisabledSystemPkg(p.packageName);
4627 }
4628 if (ps == null) {
4629 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4630 return false;
4631 } else {
4632 Log.i(TAG, "Deleting system pkg from data partition");
4633 }
4634 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004635 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004636 boolean deleteCodeAndResources = false;
4637 if (ps.versionCode < p.mVersionCode) {
4638 // Delete code and resources for downgrades
4639 deleteCodeAndResources = true;
4640 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4641 flags &= ~PackageManager.DONT_DELETE_DATA;
4642 }
4643 } else {
4644 // Preserve data by setting flag
4645 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4646 flags |= PackageManager.DONT_DELETE_DATA;
4647 }
4648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4650 if (!ret) {
4651 return false;
4652 }
4653 synchronized (mPackages) {
4654 // Reinstate the old system package
4655 mSettings.enableSystemPackageLP(p.packageName);
4656 }
4657 // Install the system package
4658 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4659 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4660 SCAN_MONITOR);
4661
4662 if (newPkg == null) {
4663 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4664 return false;
4665 }
4666 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004667 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 mSettings.writeLP();
4669 }
4670 return true;
4671 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004672
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004673 private void deletePackageResourcesLI(String packageName,
4674 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004675 if (sourceDir != null) {
4676 File sourceFile = new File(sourceDir);
4677 if (!sourceFile.exists()) {
4678 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4679 }
4680 // Delete application's code and resources
4681 sourceFile.delete();
4682 if (mInstaller != null) {
4683 int retCode = mInstaller.rmdex(sourceFile.toString());
4684 if (retCode < 0) {
4685 Log.w(TAG, "Couldn't remove dex file for package: "
4686 + packageName + " at location "
4687 + sourceFile.toString() + ", retcode=" + retCode);
4688 // we don't consider this to be a failure of the core package deletion
4689 }
4690 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004691 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004692 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4693 final File publicSourceFile = new File(publicSourceDir);
4694 if (!publicSourceFile.exists()) {
4695 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4696 }
4697 if (publicSourceFile.exists()) {
4698 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004699 }
4700 }
4701 }
4702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4704 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4705 ApplicationInfo applicationInfo = p.applicationInfo;
4706 if (applicationInfo == null) {
4707 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4708 return false;
4709 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004710 if (outInfo != null) {
4711 outInfo.uid = applicationInfo.uid;
4712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713
4714 // Delete package data from internal structures and also remove data if flag is set
4715 removePackageDataLI(p, outInfo, flags);
4716
4717 // Delete application code and resources
4718 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004719 deletePackageResourcesLI(applicationInfo.packageName,
4720 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 }
4722 return true;
4723 }
4724
4725 /*
4726 * This method handles package deletion in general
4727 */
4728 private boolean deletePackageLI(String packageName,
4729 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4730 if (packageName == null) {
4731 Log.w(TAG, "Attempt to delete null packageName.");
4732 return false;
4733 }
4734 PackageParser.Package p;
4735 boolean dataOnly = false;
4736 synchronized (mPackages) {
4737 p = mPackages.get(packageName);
4738 if (p == null) {
4739 //this retrieves partially installed apps
4740 dataOnly = true;
4741 PackageSetting ps = mSettings.mPackages.get(packageName);
4742 if (ps == null) {
4743 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4744 return false;
4745 }
4746 p = ps.pkg;
4747 }
4748 }
4749 if (p == null) {
4750 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4751 return false;
4752 }
4753
4754 if (dataOnly) {
4755 // Delete application data first
4756 removePackageDataLI(p, outInfo, flags);
4757 return true;
4758 }
4759 // At this point the package should have ApplicationInfo associated with it
4760 if (p.applicationInfo == null) {
4761 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4762 return false;
4763 }
4764 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4765 Log.i(TAG, "Removing system package:"+p.packageName);
4766 // When an updated system application is deleted we delete the existing resources as well and
4767 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004768 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 }
4770 Log.i(TAG, "Removing non-system package:"+p.packageName);
4771 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4772 }
4773
4774 public void clearApplicationUserData(final String packageName,
4775 final IPackageDataObserver observer) {
4776 mContext.enforceCallingOrSelfPermission(
4777 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4778 // Queue up an async operation since the package deletion may take a little while.
4779 mHandler.post(new Runnable() {
4780 public void run() {
4781 mHandler.removeCallbacks(this);
4782 final boolean succeeded;
4783 synchronized (mInstallLock) {
4784 succeeded = clearApplicationUserDataLI(packageName);
4785 }
4786 if (succeeded) {
4787 // invoke DeviceStorageMonitor's update method to clear any notifications
4788 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4789 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4790 if (dsm != null) {
4791 dsm.updateMemory();
4792 }
4793 }
4794 if(observer != null) {
4795 try {
4796 observer.onRemoveCompleted(packageName, succeeded);
4797 } catch (RemoteException e) {
4798 Log.i(TAG, "Observer no longer exists.");
4799 }
4800 } //end if observer
4801 } //end run
4802 });
4803 }
4804
4805 private boolean clearApplicationUserDataLI(String packageName) {
4806 if (packageName == null) {
4807 Log.w(TAG, "Attempt to delete null packageName.");
4808 return false;
4809 }
4810 PackageParser.Package p;
4811 boolean dataOnly = false;
4812 synchronized (mPackages) {
4813 p = mPackages.get(packageName);
4814 if(p == null) {
4815 dataOnly = true;
4816 PackageSetting ps = mSettings.mPackages.get(packageName);
4817 if((ps == null) || (ps.pkg == null)) {
4818 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4819 return false;
4820 }
4821 p = ps.pkg;
4822 }
4823 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004824 boolean useEncryptedFSDir = false;
4825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 if(!dataOnly) {
4827 //need to check this only for fully installed applications
4828 if (p == null) {
4829 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4830 return false;
4831 }
4832 final ApplicationInfo applicationInfo = p.applicationInfo;
4833 if (applicationInfo == null) {
4834 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4835 return false;
4836 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004837 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 }
4839 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004840 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 if (retCode < 0) {
4842 Log.w(TAG, "Couldn't remove cache files for package: "
4843 + packageName);
4844 return false;
4845 }
4846 }
4847 return true;
4848 }
4849
4850 public void deleteApplicationCacheFiles(final String packageName,
4851 final IPackageDataObserver observer) {
4852 mContext.enforceCallingOrSelfPermission(
4853 android.Manifest.permission.DELETE_CACHE_FILES, null);
4854 // Queue up an async operation since the package deletion may take a little while.
4855 mHandler.post(new Runnable() {
4856 public void run() {
4857 mHandler.removeCallbacks(this);
4858 final boolean succeded;
4859 synchronized (mInstallLock) {
4860 succeded = deleteApplicationCacheFilesLI(packageName);
4861 }
4862 if(observer != null) {
4863 try {
4864 observer.onRemoveCompleted(packageName, succeded);
4865 } catch (RemoteException e) {
4866 Log.i(TAG, "Observer no longer exists.");
4867 }
4868 } //end if observer
4869 } //end run
4870 });
4871 }
4872
4873 private boolean deleteApplicationCacheFilesLI(String packageName) {
4874 if (packageName == null) {
4875 Log.w(TAG, "Attempt to delete null packageName.");
4876 return false;
4877 }
4878 PackageParser.Package p;
4879 synchronized (mPackages) {
4880 p = mPackages.get(packageName);
4881 }
4882 if (p == null) {
4883 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4884 return false;
4885 }
4886 final ApplicationInfo applicationInfo = p.applicationInfo;
4887 if (applicationInfo == null) {
4888 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4889 return false;
4890 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004891 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004893 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 if (retCode < 0) {
4895 Log.w(TAG, "Couldn't remove cache files for package: "
4896 + packageName);
4897 return false;
4898 }
4899 }
4900 return true;
4901 }
4902
4903 public void getPackageSizeInfo(final String packageName,
4904 final IPackageStatsObserver observer) {
4905 mContext.enforceCallingOrSelfPermission(
4906 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4907 // Queue up an async operation since the package deletion may take a little while.
4908 mHandler.post(new Runnable() {
4909 public void run() {
4910 mHandler.removeCallbacks(this);
4911 PackageStats lStats = new PackageStats(packageName);
4912 final boolean succeded;
4913 synchronized (mInstallLock) {
4914 succeded = getPackageSizeInfoLI(packageName, lStats);
4915 }
4916 if(observer != null) {
4917 try {
4918 observer.onGetStatsCompleted(lStats, succeded);
4919 } catch (RemoteException e) {
4920 Log.i(TAG, "Observer no longer exists.");
4921 }
4922 } //end if observer
4923 } //end run
4924 });
4925 }
4926
4927 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4928 if (packageName == null) {
4929 Log.w(TAG, "Attempt to get size of null packageName.");
4930 return false;
4931 }
4932 PackageParser.Package p;
4933 boolean dataOnly = false;
4934 synchronized (mPackages) {
4935 p = mPackages.get(packageName);
4936 if(p == null) {
4937 dataOnly = true;
4938 PackageSetting ps = mSettings.mPackages.get(packageName);
4939 if((ps == null) || (ps.pkg == null)) {
4940 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4941 return false;
4942 }
4943 p = ps.pkg;
4944 }
4945 }
4946 String publicSrcDir = null;
4947 if(!dataOnly) {
4948 final ApplicationInfo applicationInfo = p.applicationInfo;
4949 if (applicationInfo == null) {
4950 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4951 return false;
4952 }
4953 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4954 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004955 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 if (mInstaller != null) {
4957 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08004958 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 if (res < 0) {
4960 return false;
4961 } else {
4962 return true;
4963 }
4964 }
4965 return true;
4966 }
4967
4968
4969 public void addPackageToPreferred(String packageName) {
4970 mContext.enforceCallingOrSelfPermission(
4971 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4972
4973 synchronized (mPackages) {
4974 PackageParser.Package p = mPackages.get(packageName);
4975 if (p == null) {
4976 return;
4977 }
4978 PackageSetting ps = (PackageSetting)p.mExtras;
4979 if (ps != null) {
4980 mSettings.mPreferredPackages.remove(ps);
4981 mSettings.mPreferredPackages.add(0, ps);
4982 updatePreferredIndicesLP();
4983 mSettings.writeLP();
4984 }
4985 }
4986 }
4987
4988 public void removePackageFromPreferred(String packageName) {
4989 mContext.enforceCallingOrSelfPermission(
4990 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4991
4992 synchronized (mPackages) {
4993 PackageParser.Package p = mPackages.get(packageName);
4994 if (p == null) {
4995 return;
4996 }
4997 if (p.mPreferredOrder > 0) {
4998 PackageSetting ps = (PackageSetting)p.mExtras;
4999 if (ps != null) {
5000 mSettings.mPreferredPackages.remove(ps);
5001 p.mPreferredOrder = 0;
5002 updatePreferredIndicesLP();
5003 mSettings.writeLP();
5004 }
5005 }
5006 }
5007 }
5008
5009 private void updatePreferredIndicesLP() {
5010 final ArrayList<PackageSetting> pkgs
5011 = mSettings.mPreferredPackages;
5012 final int N = pkgs.size();
5013 for (int i=0; i<N; i++) {
5014 pkgs.get(i).pkg.mPreferredOrder = N - i;
5015 }
5016 }
5017
5018 public List<PackageInfo> getPreferredPackages(int flags) {
5019 synchronized (mPackages) {
5020 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
5021 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
5022 final int N = pref.size();
5023 for (int i=0; i<N; i++) {
5024 res.add(generatePackageInfo(pref.get(i).pkg, flags));
5025 }
5026 return res;
5027 }
5028 }
5029
5030 public void addPreferredActivity(IntentFilter filter, int match,
5031 ComponentName[] set, ComponentName activity) {
5032 mContext.enforceCallingOrSelfPermission(
5033 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5034
5035 synchronized (mPackages) {
5036 Log.i(TAG, "Adding preferred activity " + activity + ":");
5037 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5038 mSettings.mPreferredActivities.addFilter(
5039 new PreferredActivity(filter, match, set, activity));
5040 mSettings.writeLP();
5041 }
5042 }
5043
Satish Sampath8dbe6122009-06-02 23:35:54 +01005044 public void replacePreferredActivity(IntentFilter filter, int match,
5045 ComponentName[] set, ComponentName activity) {
5046 mContext.enforceCallingOrSelfPermission(
5047 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5048 if (filter.countActions() != 1) {
5049 throw new IllegalArgumentException(
5050 "replacePreferredActivity expects filter to have only 1 action.");
5051 }
5052 if (filter.countCategories() != 1) {
5053 throw new IllegalArgumentException(
5054 "replacePreferredActivity expects filter to have only 1 category.");
5055 }
5056 if (filter.countDataAuthorities() != 0
5057 || filter.countDataPaths() != 0
5058 || filter.countDataSchemes() != 0
5059 || filter.countDataTypes() != 0) {
5060 throw new IllegalArgumentException(
5061 "replacePreferredActivity expects filter to have no data authorities, " +
5062 "paths, schemes or types.");
5063 }
5064 synchronized (mPackages) {
5065 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5066 String action = filter.getAction(0);
5067 String category = filter.getCategory(0);
5068 while (it.hasNext()) {
5069 PreferredActivity pa = it.next();
5070 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5071 it.remove();
5072 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5073 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5074 }
5075 }
5076 addPreferredActivity(filter, match, set, activity);
5077 }
5078 }
5079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 public void clearPackagePreferredActivities(String packageName) {
5081 mContext.enforceCallingOrSelfPermission(
5082 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5083
5084 synchronized (mPackages) {
5085 if (clearPackagePreferredActivitiesLP(packageName)) {
5086 mSettings.writeLP();
5087 }
5088 }
5089 }
5090
5091 boolean clearPackagePreferredActivitiesLP(String packageName) {
5092 boolean changed = false;
5093 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5094 while (it.hasNext()) {
5095 PreferredActivity pa = it.next();
5096 if (pa.mActivity.getPackageName().equals(packageName)) {
5097 it.remove();
5098 changed = true;
5099 }
5100 }
5101 return changed;
5102 }
5103
5104 public int getPreferredActivities(List<IntentFilter> outFilters,
5105 List<ComponentName> outActivities, String packageName) {
5106
5107 int num = 0;
5108 synchronized (mPackages) {
5109 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5110 while (it.hasNext()) {
5111 PreferredActivity pa = it.next();
5112 if (packageName == null
5113 || pa.mActivity.getPackageName().equals(packageName)) {
5114 if (outFilters != null) {
5115 outFilters.add(new IntentFilter(pa));
5116 }
5117 if (outActivities != null) {
5118 outActivities.add(pa.mActivity);
5119 }
5120 }
5121 }
5122 }
5123
5124 return num;
5125 }
5126
5127 public void setApplicationEnabledSetting(String appPackageName,
5128 int newState, int flags) {
5129 setEnabledSetting(appPackageName, null, newState, flags);
5130 }
5131
5132 public void setComponentEnabledSetting(ComponentName componentName,
5133 int newState, int flags) {
5134 setEnabledSetting(componentName.getPackageName(),
5135 componentName.getClassName(), newState, flags);
5136 }
5137
5138 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005139 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5141 || newState == COMPONENT_ENABLED_STATE_ENABLED
5142 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5143 throw new IllegalArgumentException("Invalid new component state: "
5144 + newState);
5145 }
5146 PackageSetting pkgSetting;
5147 final int uid = Binder.getCallingUid();
5148 final int permission = mContext.checkCallingPermission(
5149 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5150 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005151 boolean sendNow = false;
5152 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005153 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005155 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005157 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005159 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005161 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 }
5163 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005164 "Unknown component: " + packageName
5165 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 }
5167 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5168 throw new SecurityException(
5169 "Permission Denial: attempt to change component state from pid="
5170 + Binder.getCallingPid()
5171 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5172 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005173 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005174 // We're dealing with an application/package level state change
5175 pkgSetting.enabled = newState;
5176 } else {
5177 // We're dealing with a component level state change
5178 switch (newState) {
5179 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005180 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 break;
5182 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005183 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 break;
5185 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005186 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 break;
5188 default:
5189 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005190 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 }
5192 }
5193 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005194 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005195 components = mPendingBroadcasts.get(packageName);
5196 boolean newPackage = components == null;
5197 if (newPackage) {
5198 components = new ArrayList<String>();
5199 }
5200 if (!components.contains(componentName)) {
5201 components.add(componentName);
5202 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005203 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5204 sendNow = true;
5205 // Purge entry from pending broadcast list if another one exists already
5206 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005207 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005208 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005209 if (newPackage) {
5210 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005211 }
5212 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5213 // Schedule a message
5214 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5215 }
5216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 long callingId = Binder.clearCallingIdentity();
5220 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005221 if (sendNow) {
5222 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005223 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 } finally {
5226 Binder.restoreCallingIdentity(callingId);
5227 }
5228 }
5229
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005230 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005231 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5232 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5233 + " components=" + componentNames);
5234 Bundle extras = new Bundle(4);
5235 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5236 String nameList[] = new String[componentNames.size()];
5237 componentNames.toArray(nameList);
5238 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005239 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5240 extras.putInt(Intent.EXTRA_UID, packageUid);
5241 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
5242 }
5243
Jacek Surazski65e13172009-04-28 15:26:38 +02005244 public String getInstallerPackageName(String packageName) {
5245 synchronized (mPackages) {
5246 PackageSetting pkg = mSettings.mPackages.get(packageName);
5247 if (pkg == null) {
5248 throw new IllegalArgumentException("Unknown package: " + packageName);
5249 }
5250 return pkg.installerPackageName;
5251 }
5252 }
5253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 public int getApplicationEnabledSetting(String appPackageName) {
5255 synchronized (mPackages) {
5256 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5257 if (pkg == null) {
5258 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5259 }
5260 return pkg.enabled;
5261 }
5262 }
5263
5264 public int getComponentEnabledSetting(ComponentName componentName) {
5265 synchronized (mPackages) {
5266 final String packageNameStr = componentName.getPackageName();
5267 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5268 if (pkg == null) {
5269 throw new IllegalArgumentException("Unknown component: " + componentName);
5270 }
5271 final String classNameStr = componentName.getClassName();
5272 return pkg.currentEnabledStateLP(classNameStr);
5273 }
5274 }
5275
5276 public void enterSafeMode() {
5277 if (!mSystemReady) {
5278 mSafeMode = true;
5279 }
5280 }
5281
5282 public void systemReady() {
5283 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005284
5285 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005286 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005287 mContext.getContentResolver(),
5288 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005289 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005290 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005291 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 }
5294
5295 public boolean isSafeMode() {
5296 return mSafeMode;
5297 }
5298
5299 public boolean hasSystemUidErrors() {
5300 return mHasSystemUidErrors;
5301 }
5302
5303 static String arrayToString(int[] array) {
5304 StringBuffer buf = new StringBuffer(128);
5305 buf.append('[');
5306 if (array != null) {
5307 for (int i=0; i<array.length; i++) {
5308 if (i > 0) buf.append(", ");
5309 buf.append(array[i]);
5310 }
5311 }
5312 buf.append(']');
5313 return buf.toString();
5314 }
5315
5316 @Override
5317 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5318 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5319 != PackageManager.PERMISSION_GRANTED) {
5320 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5321 + Binder.getCallingPid()
5322 + ", uid=" + Binder.getCallingUid()
5323 + " without permission "
5324 + android.Manifest.permission.DUMP);
5325 return;
5326 }
5327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 synchronized (mPackages) {
5329 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005330 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 pw.println(" ");
5332 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005333 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 pw.println(" ");
5335 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005336 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 pw.println(" ");
5338 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005339 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 pw.println(" ");
5341 pw.println("Preferred Packages:");
5342 {
5343 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005344 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 }
5346 }
5347 pw.println(" ");
5348 pw.println("Permissions:");
5349 {
5350 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005351 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5352 pw.print(Integer.toHexString(System.identityHashCode(p)));
5353 pw.println("):");
5354 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5355 pw.print(" uid="); pw.print(p.uid);
5356 pw.print(" gids="); pw.print(arrayToString(p.gids));
5357 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 }
5359 }
5360 pw.println(" ");
5361 pw.println("Packages:");
5362 {
5363 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005364 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5365 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5366 pw.println("):");
5367 pw.print(" userId="); pw.print(ps.userId);
5368 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5369 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5370 pw.print(" pkg="); pw.println(ps.pkg);
5371 pw.print(" codePath="); pw.println(ps.codePathString);
5372 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005374 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005375 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005376 pw.print(" supportsScreens=[");
5377 boolean first = true;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005378 if ((ps.pkg.applicationInfo.flags &
5379 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005380 if (!first) pw.print(", ");
5381 first = false;
5382 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005383 }
5384 if ((ps.pkg.applicationInfo.flags &
5385 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005386 if (!first) pw.print(", ");
5387 first = false;
5388 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005389 }
5390 if ((ps.pkg.applicationInfo.flags &
5391 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005392 if (!first) pw.print(", ");
5393 first = false;
5394 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005395 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005396 if ((ps.pkg.applicationInfo.flags &
5397 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005398 if (!first) pw.print(", ");
5399 first = false;
5400 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005401 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005402 if ((ps.pkg.applicationInfo.flags &
5403 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5404 if (!first) pw.print(", ");
5405 first = false;
5406 pw.print("anyDensity");
5407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005409 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005410 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5411 pw.print(" signatures="); pw.println(ps.signatures);
5412 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5413 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5414 pw.print(" installStatus="); pw.print(ps.installStatus);
5415 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 if (ps.disabledComponents.size() > 0) {
5417 pw.println(" disabledComponents:");
5418 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005419 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 }
5421 }
5422 if (ps.enabledComponents.size() > 0) {
5423 pw.println(" enabledComponents:");
5424 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005425 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 }
5427 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005428 if (ps.grantedPermissions.size() > 0) {
5429 pw.println(" grantedPermissions:");
5430 for (String s : ps.grantedPermissions) {
5431 pw.print(" "); pw.println(s);
5432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005433 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005434 if (ps.loadedPermissions.size() > 0) {
5435 pw.println(" loadedPermissions:");
5436 for (String s : ps.loadedPermissions) {
5437 pw.print(" "); pw.println(s);
5438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 }
5440 }
5441 }
5442 pw.println(" ");
5443 pw.println("Shared Users:");
5444 {
5445 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005446 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5447 pw.print(Integer.toHexString(System.identityHashCode(su)));
5448 pw.println("):");
5449 pw.print(" userId="); pw.print(su.userId);
5450 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 pw.println(" grantedPermissions:");
5452 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005453 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 }
5455 pw.println(" loadedPermissions:");
5456 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005457 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 }
5459 }
5460 }
5461 pw.println(" ");
5462 pw.println("Settings parse messages:");
5463 pw.println(mSettings.mReadMessages.toString());
5464 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005465
5466 synchronized (mProviders) {
5467 pw.println(" ");
5468 pw.println("Registered ContentProviders:");
5469 for (PackageParser.Provider p : mProviders.values()) {
5470 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5471 pw.println(p.toString());
5472 }
5473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 }
5475
5476 static final class BasePermission {
5477 final static int TYPE_NORMAL = 0;
5478 final static int TYPE_BUILTIN = 1;
5479 final static int TYPE_DYNAMIC = 2;
5480
5481 final String name;
5482 final String sourcePackage;
5483 final int type;
5484 PackageParser.Permission perm;
5485 PermissionInfo pendingInfo;
5486 int uid;
5487 int[] gids;
5488
5489 BasePermission(String _name, String _sourcePackage, int _type) {
5490 name = _name;
5491 sourcePackage = _sourcePackage;
5492 type = _type;
5493 }
5494 }
5495
5496 static class PackageSignatures {
5497 private Signature[] mSignatures;
5498
5499 PackageSignatures(Signature[] sigs) {
5500 assignSignatures(sigs);
5501 }
5502
5503 PackageSignatures() {
5504 }
5505
5506 void writeXml(XmlSerializer serializer, String tagName,
5507 ArrayList<Signature> pastSignatures) throws IOException {
5508 if (mSignatures == null) {
5509 return;
5510 }
5511 serializer.startTag(null, tagName);
5512 serializer.attribute(null, "count",
5513 Integer.toString(mSignatures.length));
5514 for (int i=0; i<mSignatures.length; i++) {
5515 serializer.startTag(null, "cert");
5516 final Signature sig = mSignatures[i];
5517 final int sigHash = sig.hashCode();
5518 final int numPast = pastSignatures.size();
5519 int j;
5520 for (j=0; j<numPast; j++) {
5521 Signature pastSig = pastSignatures.get(j);
5522 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5523 serializer.attribute(null, "index", Integer.toString(j));
5524 break;
5525 }
5526 }
5527 if (j >= numPast) {
5528 pastSignatures.add(sig);
5529 serializer.attribute(null, "index", Integer.toString(numPast));
5530 serializer.attribute(null, "key", sig.toCharsString());
5531 }
5532 serializer.endTag(null, "cert");
5533 }
5534 serializer.endTag(null, tagName);
5535 }
5536
5537 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5538 throws IOException, XmlPullParserException {
5539 String countStr = parser.getAttributeValue(null, "count");
5540 if (countStr == null) {
5541 reportSettingsProblem(Log.WARN,
5542 "Error in package manager settings: <signatures> has"
5543 + " no count at " + parser.getPositionDescription());
5544 XmlUtils.skipCurrentTag(parser);
5545 }
5546 final int count = Integer.parseInt(countStr);
5547 mSignatures = new Signature[count];
5548 int pos = 0;
5549
5550 int outerDepth = parser.getDepth();
5551 int type;
5552 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5553 && (type != XmlPullParser.END_TAG
5554 || parser.getDepth() > outerDepth)) {
5555 if (type == XmlPullParser.END_TAG
5556 || type == XmlPullParser.TEXT) {
5557 continue;
5558 }
5559
5560 String tagName = parser.getName();
5561 if (tagName.equals("cert")) {
5562 if (pos < count) {
5563 String index = parser.getAttributeValue(null, "index");
5564 if (index != null) {
5565 try {
5566 int idx = Integer.parseInt(index);
5567 String key = parser.getAttributeValue(null, "key");
5568 if (key == null) {
5569 if (idx >= 0 && idx < pastSignatures.size()) {
5570 Signature sig = pastSignatures.get(idx);
5571 if (sig != null) {
5572 mSignatures[pos] = pastSignatures.get(idx);
5573 pos++;
5574 } else {
5575 reportSettingsProblem(Log.WARN,
5576 "Error in package manager settings: <cert> "
5577 + "index " + index + " is not defined at "
5578 + parser.getPositionDescription());
5579 }
5580 } else {
5581 reportSettingsProblem(Log.WARN,
5582 "Error in package manager settings: <cert> "
5583 + "index " + index + " is out of bounds at "
5584 + parser.getPositionDescription());
5585 }
5586 } else {
5587 while (pastSignatures.size() <= idx) {
5588 pastSignatures.add(null);
5589 }
5590 Signature sig = new Signature(key);
5591 pastSignatures.set(idx, sig);
5592 mSignatures[pos] = sig;
5593 pos++;
5594 }
5595 } catch (NumberFormatException e) {
5596 reportSettingsProblem(Log.WARN,
5597 "Error in package manager settings: <cert> "
5598 + "index " + index + " is not a number at "
5599 + parser.getPositionDescription());
5600 }
5601 } else {
5602 reportSettingsProblem(Log.WARN,
5603 "Error in package manager settings: <cert> has"
5604 + " no index at " + parser.getPositionDescription());
5605 }
5606 } else {
5607 reportSettingsProblem(Log.WARN,
5608 "Error in package manager settings: too "
5609 + "many <cert> tags, expected " + count
5610 + " at " + parser.getPositionDescription());
5611 }
5612 } else {
5613 reportSettingsProblem(Log.WARN,
5614 "Unknown element under <cert>: "
5615 + parser.getName());
5616 }
5617 XmlUtils.skipCurrentTag(parser);
5618 }
5619
5620 if (pos < count) {
5621 // Should never happen -- there is an error in the written
5622 // settings -- but if it does we don't want to generate
5623 // a bad array.
5624 Signature[] newSigs = new Signature[pos];
5625 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5626 mSignatures = newSigs;
5627 }
5628 }
5629
5630 /**
5631 * If any of the given 'sigs' is contained in the existing signatures,
5632 * then completely replace the current signatures with the ones in
5633 * 'sigs'. This is used for updating an existing package to a newly
5634 * installed version.
5635 */
5636 boolean updateSignatures(Signature[] sigs, boolean update) {
5637 if (mSignatures == null) {
5638 if (update) {
5639 assignSignatures(sigs);
5640 }
5641 return true;
5642 }
5643 if (sigs == null) {
5644 return false;
5645 }
5646
5647 for (int i=0; i<sigs.length; i++) {
5648 Signature sig = sigs[i];
5649 for (int j=0; j<mSignatures.length; j++) {
5650 if (mSignatures[j].equals(sig)) {
5651 if (update) {
5652 assignSignatures(sigs);
5653 }
5654 return true;
5655 }
5656 }
5657 }
5658 return false;
5659 }
5660
5661 /**
5662 * If any of the given 'sigs' is contained in the existing signatures,
5663 * then add in any new signatures found in 'sigs'. This is used for
5664 * including a new package into an existing shared user id.
5665 */
5666 boolean mergeSignatures(Signature[] sigs, boolean update) {
5667 if (mSignatures == null) {
5668 if (update) {
5669 assignSignatures(sigs);
5670 }
5671 return true;
5672 }
5673 if (sigs == null) {
5674 return false;
5675 }
5676
5677 Signature[] added = null;
5678 int addedCount = 0;
5679 boolean haveMatch = false;
5680 for (int i=0; i<sigs.length; i++) {
5681 Signature sig = sigs[i];
5682 boolean found = false;
5683 for (int j=0; j<mSignatures.length; j++) {
5684 if (mSignatures[j].equals(sig)) {
5685 found = true;
5686 haveMatch = true;
5687 break;
5688 }
5689 }
5690
5691 if (!found) {
5692 if (added == null) {
5693 added = new Signature[sigs.length];
5694 }
5695 added[i] = sig;
5696 addedCount++;
5697 }
5698 }
5699
5700 if (!haveMatch) {
5701 // Nothing matched -- reject the new signatures.
5702 return false;
5703 }
5704 if (added == null) {
5705 // Completely matched -- nothing else to do.
5706 return true;
5707 }
5708
5709 // Add additional signatures in.
5710 if (update) {
5711 Signature[] total = new Signature[addedCount+mSignatures.length];
5712 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5713 int j = mSignatures.length;
5714 for (int i=0; i<added.length; i++) {
5715 if (added[i] != null) {
5716 total[j] = added[i];
5717 j++;
5718 }
5719 }
5720 mSignatures = total;
5721 }
5722 return true;
5723 }
5724
5725 private void assignSignatures(Signature[] sigs) {
5726 if (sigs == null) {
5727 mSignatures = null;
5728 return;
5729 }
5730 mSignatures = new Signature[sigs.length];
5731 for (int i=0; i<sigs.length; i++) {
5732 mSignatures[i] = sigs[i];
5733 }
5734 }
5735
5736 @Override
5737 public String toString() {
5738 StringBuffer buf = new StringBuffer(128);
5739 buf.append("PackageSignatures{");
5740 buf.append(Integer.toHexString(System.identityHashCode(this)));
5741 buf.append(" [");
5742 if (mSignatures != null) {
5743 for (int i=0; i<mSignatures.length; i++) {
5744 if (i > 0) buf.append(", ");
5745 buf.append(Integer.toHexString(
5746 System.identityHashCode(mSignatures[i])));
5747 }
5748 }
5749 buf.append("]}");
5750 return buf.toString();
5751 }
5752 }
5753
5754 static class PreferredActivity extends IntentFilter {
5755 final int mMatch;
5756 final String[] mSetPackages;
5757 final String[] mSetClasses;
5758 final String[] mSetComponents;
5759 final ComponentName mActivity;
5760 final String mShortActivity;
5761 String mParseError;
5762
5763 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5764 ComponentName activity) {
5765 super(filter);
5766 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5767 mActivity = activity;
5768 mShortActivity = activity.flattenToShortString();
5769 mParseError = null;
5770 if (set != null) {
5771 final int N = set.length;
5772 String[] myPackages = new String[N];
5773 String[] myClasses = new String[N];
5774 String[] myComponents = new String[N];
5775 for (int i=0; i<N; i++) {
5776 ComponentName cn = set[i];
5777 if (cn == null) {
5778 mSetPackages = null;
5779 mSetClasses = null;
5780 mSetComponents = null;
5781 return;
5782 }
5783 myPackages[i] = cn.getPackageName().intern();
5784 myClasses[i] = cn.getClassName().intern();
5785 myComponents[i] = cn.flattenToShortString().intern();
5786 }
5787 mSetPackages = myPackages;
5788 mSetClasses = myClasses;
5789 mSetComponents = myComponents;
5790 } else {
5791 mSetPackages = null;
5792 mSetClasses = null;
5793 mSetComponents = null;
5794 }
5795 }
5796
5797 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5798 IOException {
5799 mShortActivity = parser.getAttributeValue(null, "name");
5800 mActivity = ComponentName.unflattenFromString(mShortActivity);
5801 if (mActivity == null) {
5802 mParseError = "Bad activity name " + mShortActivity;
5803 }
5804 String matchStr = parser.getAttributeValue(null, "match");
5805 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5806 String setCountStr = parser.getAttributeValue(null, "set");
5807 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5808
5809 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5810 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5811 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5812
5813 int setPos = 0;
5814
5815 int outerDepth = parser.getDepth();
5816 int type;
5817 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5818 && (type != XmlPullParser.END_TAG
5819 || parser.getDepth() > outerDepth)) {
5820 if (type == XmlPullParser.END_TAG
5821 || type == XmlPullParser.TEXT) {
5822 continue;
5823 }
5824
5825 String tagName = parser.getName();
5826 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5827 // + parser.getDepth() + " tag=" + tagName);
5828 if (tagName.equals("set")) {
5829 String name = parser.getAttributeValue(null, "name");
5830 if (name == null) {
5831 if (mParseError == null) {
5832 mParseError = "No name in set tag in preferred activity "
5833 + mShortActivity;
5834 }
5835 } else if (setPos >= setCount) {
5836 if (mParseError == null) {
5837 mParseError = "Too many set tags in preferred activity "
5838 + mShortActivity;
5839 }
5840 } else {
5841 ComponentName cn = ComponentName.unflattenFromString(name);
5842 if (cn == null) {
5843 if (mParseError == null) {
5844 mParseError = "Bad set name " + name + " in preferred activity "
5845 + mShortActivity;
5846 }
5847 } else {
5848 myPackages[setPos] = cn.getPackageName();
5849 myClasses[setPos] = cn.getClassName();
5850 myComponents[setPos] = name;
5851 setPos++;
5852 }
5853 }
5854 XmlUtils.skipCurrentTag(parser);
5855 } else if (tagName.equals("filter")) {
5856 //Log.i(TAG, "Starting to parse filter...");
5857 readFromXml(parser);
5858 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5859 // + parser.getDepth() + " tag=" + parser.getName());
5860 } else {
5861 reportSettingsProblem(Log.WARN,
5862 "Unknown element under <preferred-activities>: "
5863 + parser.getName());
5864 XmlUtils.skipCurrentTag(parser);
5865 }
5866 }
5867
5868 if (setPos != setCount) {
5869 if (mParseError == null) {
5870 mParseError = "Not enough set tags (expected " + setCount
5871 + " but found " + setPos + ") in " + mShortActivity;
5872 }
5873 }
5874
5875 mSetPackages = myPackages;
5876 mSetClasses = myClasses;
5877 mSetComponents = myComponents;
5878 }
5879
5880 public void writeToXml(XmlSerializer serializer) throws IOException {
5881 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5882 serializer.attribute(null, "name", mShortActivity);
5883 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5884 serializer.attribute(null, "set", Integer.toString(NS));
5885 for (int s=0; s<NS; s++) {
5886 serializer.startTag(null, "set");
5887 serializer.attribute(null, "name", mSetComponents[s]);
5888 serializer.endTag(null, "set");
5889 }
5890 serializer.startTag(null, "filter");
5891 super.writeToXml(serializer);
5892 serializer.endTag(null, "filter");
5893 }
5894
5895 boolean sameSet(List<ResolveInfo> query, int priority) {
5896 if (mSetPackages == null) return false;
5897 final int NQ = query.size();
5898 final int NS = mSetPackages.length;
5899 int numMatch = 0;
5900 for (int i=0; i<NQ; i++) {
5901 ResolveInfo ri = query.get(i);
5902 if (ri.priority != priority) continue;
5903 ActivityInfo ai = ri.activityInfo;
5904 boolean good = false;
5905 for (int j=0; j<NS; j++) {
5906 if (mSetPackages[j].equals(ai.packageName)
5907 && mSetClasses[j].equals(ai.name)) {
5908 numMatch++;
5909 good = true;
5910 break;
5911 }
5912 }
5913 if (!good) return false;
5914 }
5915 return numMatch == NS;
5916 }
5917 }
5918
5919 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005920 int pkgFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921
5922 HashSet<String> grantedPermissions = new HashSet<String>();
5923 int[] gids;
5924
5925 HashSet<String> loadedPermissions = new HashSet<String>();
5926
5927 GrantedPermissions(int pkgFlags) {
5928 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5929 }
5930 }
5931
5932 /**
5933 * Settings base class for pending and resolved classes.
5934 */
5935 static class PackageSettingBase extends GrantedPermissions {
5936 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005937 File codePath;
5938 String codePathString;
5939 File resourcePath;
5940 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 private long timeStamp;
5942 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005943 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944
5945 PackageSignatures signatures = new PackageSignatures();
5946
5947 boolean permissionsFixed;
5948
5949 /* Explicitly disabled components */
5950 HashSet<String> disabledComponents = new HashSet<String>(0);
5951 /* Explicitly enabled components */
5952 HashSet<String> enabledComponents = new HashSet<String>(0);
5953 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5954 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005955
5956 /* package name of the app that installed this package */
5957 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958
5959 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005960 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 super(pkgFlags);
5962 this.name = name;
5963 this.codePath = codePath;
5964 this.codePathString = codePath.toString();
5965 this.resourcePath = resourcePath;
5966 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005967 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 }
5969
Jacek Surazski65e13172009-04-28 15:26:38 +02005970 public void setInstallerPackageName(String packageName) {
5971 installerPackageName = packageName;
5972 }
5973
5974 String getInstallerPackageName() {
5975 return installerPackageName;
5976 }
5977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 public void setInstallStatus(int newStatus) {
5979 installStatus = newStatus;
5980 }
5981
5982 public int getInstallStatus() {
5983 return installStatus;
5984 }
5985
5986 public void setTimeStamp(long newStamp) {
5987 if (newStamp != timeStamp) {
5988 timeStamp = newStamp;
5989 timeStampString = Long.toString(newStamp);
5990 }
5991 }
5992
5993 public void setTimeStamp(long newStamp, String newStampStr) {
5994 timeStamp = newStamp;
5995 timeStampString = newStampStr;
5996 }
5997
5998 public long getTimeStamp() {
5999 return timeStamp;
6000 }
6001
6002 public String getTimeStampStr() {
6003 return timeStampString;
6004 }
6005
6006 public void copyFrom(PackageSettingBase base) {
6007 grantedPermissions = base.grantedPermissions;
6008 gids = base.gids;
6009 loadedPermissions = base.loadedPermissions;
6010
6011 timeStamp = base.timeStamp;
6012 timeStampString = base.timeStampString;
6013 signatures = base.signatures;
6014 permissionsFixed = base.permissionsFixed;
6015 disabledComponents = base.disabledComponents;
6016 enabledComponents = base.enabledComponents;
6017 enabled = base.enabled;
6018 installStatus = base.installStatus;
6019 }
6020
6021 void enableComponentLP(String componentClassName) {
6022 disabledComponents.remove(componentClassName);
6023 enabledComponents.add(componentClassName);
6024 }
6025
6026 void disableComponentLP(String componentClassName) {
6027 enabledComponents.remove(componentClassName);
6028 disabledComponents.add(componentClassName);
6029 }
6030
6031 void restoreComponentLP(String componentClassName) {
6032 enabledComponents.remove(componentClassName);
6033 disabledComponents.remove(componentClassName);
6034 }
6035
6036 int currentEnabledStateLP(String componentName) {
6037 if (enabledComponents.contains(componentName)) {
6038 return COMPONENT_ENABLED_STATE_ENABLED;
6039 } else if (disabledComponents.contains(componentName)) {
6040 return COMPONENT_ENABLED_STATE_DISABLED;
6041 } else {
6042 return COMPONENT_ENABLED_STATE_DEFAULT;
6043 }
6044 }
6045 }
6046
6047 /**
6048 * Settings data for a particular package we know about.
6049 */
6050 static final class PackageSetting extends PackageSettingBase {
6051 int userId;
6052 PackageParser.Package pkg;
6053 SharedUserSetting sharedUser;
6054
6055 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006056 int pVersionCode, int pkgFlags) {
6057 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 }
6059
6060 @Override
6061 public String toString() {
6062 return "PackageSetting{"
6063 + Integer.toHexString(System.identityHashCode(this))
6064 + " " + name + "/" + userId + "}";
6065 }
6066 }
6067
6068 /**
6069 * Settings data for a particular shared user ID we know about.
6070 */
6071 static final class SharedUserSetting extends GrantedPermissions {
6072 final String name;
6073 int userId;
6074 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6075 final PackageSignatures signatures = new PackageSignatures();
6076
6077 SharedUserSetting(String _name, int _pkgFlags) {
6078 super(_pkgFlags);
6079 name = _name;
6080 }
6081
6082 @Override
6083 public String toString() {
6084 return "SharedUserSetting{"
6085 + Integer.toHexString(System.identityHashCode(this))
6086 + " " + name + "/" + userId + "}";
6087 }
6088 }
6089
6090 /**
6091 * Holds information about dynamic settings.
6092 */
6093 private static final class Settings {
6094 private final File mSettingsFilename;
6095 private final File mBackupSettingsFilename;
6096 private final HashMap<String, PackageSetting> mPackages =
6097 new HashMap<String, PackageSetting>();
6098 // The user's preferred packages/applications, in order of preference.
6099 // First is the most preferred.
6100 private final ArrayList<PackageSetting> mPreferredPackages =
6101 new ArrayList<PackageSetting>();
6102 // List of replaced system applications
6103 final HashMap<String, PackageSetting> mDisabledSysPackages =
6104 new HashMap<String, PackageSetting>();
6105
6106 // The user's preferred activities associated with particular intent
6107 // filters.
6108 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6109 new IntentResolver<PreferredActivity, PreferredActivity>() {
6110 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006111 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006112 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006113 out.print(prefix); out.print(
6114 Integer.toHexString(System.identityHashCode(filter)));
6115 out.print(' ');
6116 out.print(filter.mActivity.flattenToShortString());
6117 out.print(" match=0x");
6118 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006120 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006122 out.print(prefix); out.print(" ");
6123 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 }
6125 }
6126 }
6127 };
6128 private final HashMap<String, SharedUserSetting> mSharedUsers =
6129 new HashMap<String, SharedUserSetting>();
6130 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6131 private final SparseArray<Object> mOtherUserIds =
6132 new SparseArray<Object>();
6133
6134 // For reading/writing settings file.
6135 private final ArrayList<Signature> mPastSignatures =
6136 new ArrayList<Signature>();
6137
6138 // Mapping from permission names to info about them.
6139 final HashMap<String, BasePermission> mPermissions =
6140 new HashMap<String, BasePermission>();
6141
6142 // Mapping from permission tree names to info about them.
6143 final HashMap<String, BasePermission> mPermissionTrees =
6144 new HashMap<String, BasePermission>();
6145
6146 private final ArrayList<String> mPendingPreferredPackages
6147 = new ArrayList<String>();
6148
6149 private final StringBuilder mReadMessages = new StringBuilder();
6150
6151 private static final class PendingPackage extends PackageSettingBase {
6152 final int sharedId;
6153
6154 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006155 int sharedId, int pVersionCode, int pkgFlags) {
6156 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006157 this.sharedId = sharedId;
6158 }
6159 }
6160 private final ArrayList<PendingPackage> mPendingPackages
6161 = new ArrayList<PendingPackage>();
6162
6163 Settings() {
6164 File dataDir = Environment.getDataDirectory();
6165 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006166 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6167 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006169 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006170 FileUtils.setPermissions(systemDir.toString(),
6171 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6172 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6173 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006174 FileUtils.setPermissions(systemSecureDir.toString(),
6175 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6176 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6177 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 mSettingsFilename = new File(systemDir, "packages.xml");
6179 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6180 }
6181
6182 PackageSetting getPackageLP(PackageParser.Package pkg,
6183 SharedUserSetting sharedUser, File codePath, File resourcePath,
6184 int pkgFlags, boolean create, boolean add) {
6185 final String name = pkg.packageName;
6186 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006187 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 return p;
6189 }
6190
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006191 PackageSetting peekPackageLP(String name) {
6192 return mPackages.get(name);
6193 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006194 PackageSetting p = mPackages.get(name);
6195 if (p != null && p.codePath.getPath().equals(codePath)) {
6196 return p;
6197 }
6198 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006199 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006200 }
6201
6202 void setInstallStatus(String pkgName, int status) {
6203 PackageSetting p = mPackages.get(pkgName);
6204 if(p != null) {
6205 if(p.getInstallStatus() != status) {
6206 p.setInstallStatus(status);
6207 }
6208 }
6209 }
6210
Jacek Surazski65e13172009-04-28 15:26:38 +02006211 void setInstallerPackageName(String pkgName,
6212 String installerPkgName) {
6213 PackageSetting p = mPackages.get(pkgName);
6214 if(p != null) {
6215 p.setInstallerPackageName(installerPkgName);
6216 }
6217 }
6218
6219 String getInstallerPackageName(String pkgName) {
6220 PackageSetting p = mPackages.get(pkgName);
6221 return (p == null) ? null : p.getInstallerPackageName();
6222 }
6223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 int getInstallStatus(String pkgName) {
6225 PackageSetting p = mPackages.get(pkgName);
6226 if(p != null) {
6227 return p.getInstallStatus();
6228 }
6229 return -1;
6230 }
6231
6232 SharedUserSetting getSharedUserLP(String name,
6233 int pkgFlags, boolean create) {
6234 SharedUserSetting s = mSharedUsers.get(name);
6235 if (s == null) {
6236 if (!create) {
6237 return null;
6238 }
6239 s = new SharedUserSetting(name, pkgFlags);
6240 if (MULTIPLE_APPLICATION_UIDS) {
6241 s.userId = newUserIdLP(s);
6242 } else {
6243 s.userId = FIRST_APPLICATION_UID;
6244 }
6245 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6246 // < 0 means we couldn't assign a userid; fall out and return
6247 // s, which is currently null
6248 if (s.userId >= 0) {
6249 mSharedUsers.put(name, s);
6250 }
6251 }
6252
6253 return s;
6254 }
6255
6256 int disableSystemPackageLP(String name) {
6257 PackageSetting p = mPackages.get(name);
6258 if(p == null) {
6259 Log.w(TAG, "Package:"+name+" is not an installed package");
6260 return -1;
6261 }
6262 PackageSetting dp = mDisabledSysPackages.get(name);
6263 // always make sure the system package code and resource paths dont change
6264 if(dp == null) {
6265 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6266 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6267 }
6268 mDisabledSysPackages.put(name, p);
6269 }
6270 return removePackageLP(name);
6271 }
6272
6273 PackageSetting enableSystemPackageLP(String name) {
6274 PackageSetting p = mDisabledSysPackages.get(name);
6275 if(p == null) {
6276 Log.w(TAG, "Package:"+name+" is not disabled");
6277 return null;
6278 }
6279 // Reset flag in ApplicationInfo object
6280 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6281 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6282 }
6283 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006284 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 mDisabledSysPackages.remove(name);
6286 return ret;
6287 }
6288
6289 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006290 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 PackageSetting p = mPackages.get(name);
6292 if (p != null) {
6293 if (p.userId == uid) {
6294 return p;
6295 }
6296 reportSettingsProblem(Log.ERROR,
6297 "Adding duplicate package, keeping first: " + name);
6298 return null;
6299 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006300 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 p.userId = uid;
6302 if (addUserIdLP(uid, p, name)) {
6303 mPackages.put(name, p);
6304 return p;
6305 }
6306 return null;
6307 }
6308
6309 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6310 SharedUserSetting s = mSharedUsers.get(name);
6311 if (s != null) {
6312 if (s.userId == uid) {
6313 return s;
6314 }
6315 reportSettingsProblem(Log.ERROR,
6316 "Adding duplicate shared user, keeping first: " + name);
6317 return null;
6318 }
6319 s = new SharedUserSetting(name, pkgFlags);
6320 s.userId = uid;
6321 if (addUserIdLP(uid, s, name)) {
6322 mSharedUsers.put(name, s);
6323 return s;
6324 }
6325 return null;
6326 }
6327
6328 private PackageSetting getPackageLP(String name,
6329 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006330 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 PackageSetting p = mPackages.get(name);
6332 if (p != null) {
6333 if (!p.codePath.equals(codePath)) {
6334 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006335 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006336 // This is an updated system app with versions in both system
6337 // and data partition. Just let the most recent version
6338 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006339 Log.w(TAG, "Trying to update system app code path from " +
6340 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006341 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006342 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006343 reportSettingsProblem(Log.WARN,
6344 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006345 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006347 }
6348 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 reportSettingsProblem(Log.WARN,
6350 "Package " + name + " shared user changed from "
6351 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6352 + " to "
6353 + (sharedUser != null ? sharedUser.name : "<nothing>")
6354 + "; replacing with new");
6355 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006356 } else {
6357 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6358 // If what we are scanning is a system package, then
6359 // make it so, regardless of whether it was previously
6360 // installed only in the data partition.
6361 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 }
6364 }
6365 if (p == null) {
6366 // Create a new PackageSettings entry. this can end up here because
6367 // of code path mismatch or user id mismatch of an updated system partition
6368 if (!create) {
6369 return null;
6370 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006371 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006373 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 if (sharedUser != null) {
6375 p.userId = sharedUser.userId;
6376 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006377 // Clone the setting here for disabled system packages
6378 PackageSetting dis = mDisabledSysPackages.get(name);
6379 if (dis != null) {
6380 // For disabled packages a new setting is created
6381 // from the existing user id. This still has to be
6382 // added to list of user id's
6383 // Copy signatures from previous setting
6384 if (dis.signatures.mSignatures != null) {
6385 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6386 }
6387 p.userId = dis.userId;
6388 // Clone permissions
6389 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6390 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6391 // Clone component info
6392 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6393 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6394 // Add new setting to list of user ids
6395 addUserIdLP(p.userId, p, name);
6396 } else {
6397 // Assign new user id
6398 p.userId = newUserIdLP(p);
6399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 } else {
6401 p.userId = FIRST_APPLICATION_UID;
6402 }
6403 if (p.userId < 0) {
6404 reportSettingsProblem(Log.WARN,
6405 "Package " + name + " could not be assigned a valid uid");
6406 return null;
6407 }
6408 if (add) {
6409 // Finish adding new package by adding it and updating shared
6410 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006411 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 }
6413 }
6414 return p;
6415 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006416
6417 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6418 File codePath, File resourcePath) {
6419 p.pkg = pkg;
6420 // Update code path if needed
6421 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6422 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006423 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006424 p.codePath = codePath;
6425 p.codePathString = codePath.toString();
6426 }
6427 //Update resource path if needed
6428 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6429 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006430 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006431 p.resourcePath = resourcePath;
6432 p.resourcePathString = resourcePath.toString();
6433 }
6434 // Update version code if needed
6435 if (pkg.mVersionCode != p.versionCode) {
6436 p.versionCode = pkg.mVersionCode;
6437 }
6438 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6439 }
6440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 // Utility method that adds a PackageSetting to mPackages and
6442 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006443 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 SharedUserSetting sharedUser) {
6445 mPackages.put(name, p);
6446 if (sharedUser != null) {
6447 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6448 reportSettingsProblem(Log.ERROR,
6449 "Package " + p.name + " was user "
6450 + p.sharedUser + " but is now " + sharedUser
6451 + "; I am not changing its files so it will probably fail!");
6452 p.sharedUser.packages.remove(p);
6453 } else if (p.userId != sharedUser.userId) {
6454 reportSettingsProblem(Log.ERROR,
6455 "Package " + p.name + " was user id " + p.userId
6456 + " but is now user " + sharedUser
6457 + " with id " + sharedUser.userId
6458 + "; I am not changing its files so it will probably fail!");
6459 }
6460
6461 sharedUser.packages.add(p);
6462 p.sharedUser = sharedUser;
6463 p.userId = sharedUser.userId;
6464 }
6465 }
6466
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006467 /*
6468 * Update the shared user setting when a package using
6469 * specifying the shared user id is removed. The gids
6470 * associated with each permission of the deleted package
6471 * are removed from the shared user's gid list only if its
6472 * not in use by other permissions of packages in the
6473 * shared user setting.
6474 */
6475 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6477 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6478 return;
6479 }
6480 // No sharedUserId
6481 if (deletedPs.sharedUser == null) {
6482 return;
6483 }
6484 SharedUserSetting sus = deletedPs.sharedUser;
6485 // Update permissions
6486 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6487 boolean used = false;
6488 if (!sus.grantedPermissions.contains (eachPerm)) {
6489 continue;
6490 }
6491 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006492 if (pkg.pkg != null &&
6493 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6494 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006495 used = true;
6496 break;
6497 }
6498 }
6499 if (!used) {
6500 // can safely delete this permission from list
6501 sus.grantedPermissions.remove(eachPerm);
6502 sus.loadedPermissions.remove(eachPerm);
6503 }
6504 }
6505 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006506 int newGids[] = globalGids;
6507 for (String eachPerm : sus.grantedPermissions) {
6508 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006509 if (bp != null) {
6510 newGids = appendInts(newGids, bp.gids);
6511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 }
6513 sus.gids = newGids;
6514 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 private int removePackageLP(String name) {
6517 PackageSetting p = mPackages.get(name);
6518 if (p != null) {
6519 mPackages.remove(name);
6520 if (p.sharedUser != null) {
6521 p.sharedUser.packages.remove(p);
6522 if (p.sharedUser.packages.size() == 0) {
6523 mSharedUsers.remove(p.sharedUser.name);
6524 removeUserIdLP(p.sharedUser.userId);
6525 return p.sharedUser.userId;
6526 }
6527 } else {
6528 removeUserIdLP(p.userId);
6529 return p.userId;
6530 }
6531 }
6532 return -1;
6533 }
6534
6535 private boolean addUserIdLP(int uid, Object obj, Object name) {
6536 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6537 return false;
6538 }
6539
6540 if (uid >= FIRST_APPLICATION_UID) {
6541 int N = mUserIds.size();
6542 final int index = uid - FIRST_APPLICATION_UID;
6543 while (index >= N) {
6544 mUserIds.add(null);
6545 N++;
6546 }
6547 if (mUserIds.get(index) != null) {
6548 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006549 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006550 + " name=" + name);
6551 return false;
6552 }
6553 mUserIds.set(index, obj);
6554 } else {
6555 if (mOtherUserIds.get(uid) != null) {
6556 reportSettingsProblem(Log.ERROR,
6557 "Adding duplicate shared id: " + uid
6558 + " name=" + name);
6559 return false;
6560 }
6561 mOtherUserIds.put(uid, obj);
6562 }
6563 return true;
6564 }
6565
6566 public Object getUserIdLP(int uid) {
6567 if (uid >= FIRST_APPLICATION_UID) {
6568 int N = mUserIds.size();
6569 final int index = uid - FIRST_APPLICATION_UID;
6570 return index < N ? mUserIds.get(index) : null;
6571 } else {
6572 return mOtherUserIds.get(uid);
6573 }
6574 }
6575
6576 private void removeUserIdLP(int uid) {
6577 if (uid >= FIRST_APPLICATION_UID) {
6578 int N = mUserIds.size();
6579 final int index = uid - FIRST_APPLICATION_UID;
6580 if (index < N) mUserIds.set(index, null);
6581 } else {
6582 mOtherUserIds.remove(uid);
6583 }
6584 }
6585
6586 void writeLP() {
6587 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6588
6589 // Keep the old settings around until we know the new ones have
6590 // been successfully written.
6591 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006592 // Presence of backup settings file indicates that we failed
6593 // to persist settings earlier. So preserve the older
6594 // backup for future reference since the current settings
6595 // might have been corrupted.
6596 if (!mBackupSettingsFilename.exists()) {
6597 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6598 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6599 return;
6600 }
6601 } else {
6602 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 }
6605
6606 mPastSignatures.clear();
6607
6608 try {
6609 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6610
6611 //XmlSerializer serializer = XmlUtils.serializerInstance();
6612 XmlSerializer serializer = new FastXmlSerializer();
6613 serializer.setOutput(str, "utf-8");
6614 serializer.startDocument(null, true);
6615 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6616
6617 serializer.startTag(null, "packages");
6618
6619 serializer.startTag(null, "permission-trees");
6620 for (BasePermission bp : mPermissionTrees.values()) {
6621 writePermission(serializer, bp);
6622 }
6623 serializer.endTag(null, "permission-trees");
6624
6625 serializer.startTag(null, "permissions");
6626 for (BasePermission bp : mPermissions.values()) {
6627 writePermission(serializer, bp);
6628 }
6629 serializer.endTag(null, "permissions");
6630
6631 for (PackageSetting pkg : mPackages.values()) {
6632 writePackage(serializer, pkg);
6633 }
6634
6635 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6636 writeDisabledSysPackage(serializer, pkg);
6637 }
6638
6639 serializer.startTag(null, "preferred-packages");
6640 int N = mPreferredPackages.size();
6641 for (int i=0; i<N; i++) {
6642 PackageSetting pkg = mPreferredPackages.get(i);
6643 serializer.startTag(null, "item");
6644 serializer.attribute(null, "name", pkg.name);
6645 serializer.endTag(null, "item");
6646 }
6647 serializer.endTag(null, "preferred-packages");
6648
6649 serializer.startTag(null, "preferred-activities");
6650 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6651 serializer.startTag(null, "item");
6652 pa.writeToXml(serializer);
6653 serializer.endTag(null, "item");
6654 }
6655 serializer.endTag(null, "preferred-activities");
6656
6657 for (SharedUserSetting usr : mSharedUsers.values()) {
6658 serializer.startTag(null, "shared-user");
6659 serializer.attribute(null, "name", usr.name);
6660 serializer.attribute(null, "userId",
6661 Integer.toString(usr.userId));
6662 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6663 serializer.startTag(null, "perms");
6664 for (String name : usr.grantedPermissions) {
6665 serializer.startTag(null, "item");
6666 serializer.attribute(null, "name", name);
6667 serializer.endTag(null, "item");
6668 }
6669 serializer.endTag(null, "perms");
6670 serializer.endTag(null, "shared-user");
6671 }
6672
6673 serializer.endTag(null, "packages");
6674
6675 serializer.endDocument();
6676
6677 str.flush();
6678 str.close();
6679
6680 // New settings successfully written, old ones are no longer
6681 // needed.
6682 mBackupSettingsFilename.delete();
6683 FileUtils.setPermissions(mSettingsFilename.toString(),
6684 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6685 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6686 |FileUtils.S_IROTH,
6687 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006688 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006689
6690 } catch(XmlPullParserException e) {
6691 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006692 } catch(java.io.IOException e) {
6693 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006694 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006695 // Clean up partially written file
6696 if (mSettingsFilename.exists()) {
6697 if (!mSettingsFilename.delete()) {
6698 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6699 }
6700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 //Debug.stopMethodTracing();
6702 }
6703
6704 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
6705 throws java.io.IOException {
6706 serializer.startTag(null, "updated-package");
6707 serializer.attribute(null, "name", pkg.name);
6708 serializer.attribute(null, "codePath", pkg.codePathString);
6709 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006710 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006711 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6712 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6713 }
6714 if (pkg.sharedUser == null) {
6715 serializer.attribute(null, "userId",
6716 Integer.toString(pkg.userId));
6717 } else {
6718 serializer.attribute(null, "sharedUserId",
6719 Integer.toString(pkg.userId));
6720 }
6721 serializer.startTag(null, "perms");
6722 if (pkg.sharedUser == null) {
6723 // If this is a shared user, the permissions will
6724 // be written there. We still need to write an
6725 // empty permissions list so permissionsFixed will
6726 // be set.
6727 for (final String name : pkg.grantedPermissions) {
6728 BasePermission bp = mPermissions.get(name);
6729 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6730 // We only need to write signature or system permissions but this wont
6731 // match the semantics of grantedPermissions. So write all permissions.
6732 serializer.startTag(null, "item");
6733 serializer.attribute(null, "name", name);
6734 serializer.endTag(null, "item");
6735 }
6736 }
6737 }
6738 serializer.endTag(null, "perms");
6739 serializer.endTag(null, "updated-package");
6740 }
6741
6742 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6743 throws java.io.IOException {
6744 serializer.startTag(null, "package");
6745 serializer.attribute(null, "name", pkg.name);
6746 serializer.attribute(null, "codePath", pkg.codePathString);
6747 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6748 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6749 }
6750 serializer.attribute(null, "system",
6751 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6752 ? "true" : "false");
6753 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006754 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 if (pkg.sharedUser == null) {
6756 serializer.attribute(null, "userId",
6757 Integer.toString(pkg.userId));
6758 } else {
6759 serializer.attribute(null, "sharedUserId",
6760 Integer.toString(pkg.userId));
6761 }
6762 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6763 serializer.attribute(null, "enabled",
6764 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6765 ? "true" : "false");
6766 }
6767 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6768 serializer.attribute(null, "installStatus", "false");
6769 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006770 if (pkg.installerPackageName != null) {
6771 serializer.attribute(null, "installer", pkg.installerPackageName);
6772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6774 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6775 serializer.startTag(null, "perms");
6776 if (pkg.sharedUser == null) {
6777 // If this is a shared user, the permissions will
6778 // be written there. We still need to write an
6779 // empty permissions list so permissionsFixed will
6780 // be set.
6781 for (final String name : pkg.grantedPermissions) {
6782 serializer.startTag(null, "item");
6783 serializer.attribute(null, "name", name);
6784 serializer.endTag(null, "item");
6785 }
6786 }
6787 serializer.endTag(null, "perms");
6788 }
6789 if (pkg.disabledComponents.size() > 0) {
6790 serializer.startTag(null, "disabled-components");
6791 for (final String name : pkg.disabledComponents) {
6792 serializer.startTag(null, "item");
6793 serializer.attribute(null, "name", name);
6794 serializer.endTag(null, "item");
6795 }
6796 serializer.endTag(null, "disabled-components");
6797 }
6798 if (pkg.enabledComponents.size() > 0) {
6799 serializer.startTag(null, "enabled-components");
6800 for (final String name : pkg.enabledComponents) {
6801 serializer.startTag(null, "item");
6802 serializer.attribute(null, "name", name);
6803 serializer.endTag(null, "item");
6804 }
6805 serializer.endTag(null, "enabled-components");
6806 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 serializer.endTag(null, "package");
6809 }
6810
6811 void writePermission(XmlSerializer serializer, BasePermission bp)
6812 throws XmlPullParserException, java.io.IOException {
6813 if (bp.type != BasePermission.TYPE_BUILTIN
6814 && bp.sourcePackage != null) {
6815 serializer.startTag(null, "item");
6816 serializer.attribute(null, "name", bp.name);
6817 serializer.attribute(null, "package", bp.sourcePackage);
6818 if (DEBUG_SETTINGS) Log.v(TAG,
6819 "Writing perm: name=" + bp.name + " type=" + bp.type);
6820 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6821 PermissionInfo pi = bp.perm != null ? bp.perm.info
6822 : bp.pendingInfo;
6823 if (pi != null) {
6824 serializer.attribute(null, "type", "dynamic");
6825 if (pi.icon != 0) {
6826 serializer.attribute(null, "icon",
6827 Integer.toString(pi.icon));
6828 }
6829 if (pi.nonLocalizedLabel != null) {
6830 serializer.attribute(null, "label",
6831 pi.nonLocalizedLabel.toString());
6832 }
6833 if (pi.protectionLevel !=
6834 PermissionInfo.PROTECTION_NORMAL) {
6835 serializer.attribute(null, "protection",
6836 Integer.toString(pi.protectionLevel));
6837 }
6838 }
6839 }
6840 serializer.endTag(null, "item");
6841 }
6842 }
6843
6844 String getReadMessagesLP() {
6845 return mReadMessages.toString();
6846 }
6847
Oscar Montemayora8529f62009-11-18 10:14:20 -08006848 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6850 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006851 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006852 while(its.hasNext()) {
6853 String key = its.next();
6854 PackageSetting ps = mPackages.get(key);
6855 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006856 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006857 }
6858 }
6859 return ret;
6860 }
6861
6862 boolean readLP() {
6863 FileInputStream str = null;
6864 if (mBackupSettingsFilename.exists()) {
6865 try {
6866 str = new FileInputStream(mBackupSettingsFilename);
6867 mReadMessages.append("Reading from backup settings file\n");
6868 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006869 if (mSettingsFilename.exists()) {
6870 // If both the backup and settings file exist, we
6871 // ignore the settings since it might have been
6872 // corrupted.
6873 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6874 mSettingsFilename.delete();
6875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 } catch (java.io.IOException e) {
6877 // We'll try for the normal settings file.
6878 }
6879 }
6880
6881 mPastSignatures.clear();
6882
6883 try {
6884 if (str == null) {
6885 if (!mSettingsFilename.exists()) {
6886 mReadMessages.append("No settings file found\n");
6887 Log.i(TAG, "No current settings file!");
6888 return false;
6889 }
6890 str = new FileInputStream(mSettingsFilename);
6891 }
6892 XmlPullParser parser = Xml.newPullParser();
6893 parser.setInput(str, null);
6894
6895 int type;
6896 while ((type=parser.next()) != XmlPullParser.START_TAG
6897 && type != XmlPullParser.END_DOCUMENT) {
6898 ;
6899 }
6900
6901 if (type != XmlPullParser.START_TAG) {
6902 mReadMessages.append("No start tag found in settings file\n");
6903 Log.e(TAG, "No start tag found in package manager settings");
6904 return false;
6905 }
6906
6907 int outerDepth = parser.getDepth();
6908 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6909 && (type != XmlPullParser.END_TAG
6910 || parser.getDepth() > outerDepth)) {
6911 if (type == XmlPullParser.END_TAG
6912 || type == XmlPullParser.TEXT) {
6913 continue;
6914 }
6915
6916 String tagName = parser.getName();
6917 if (tagName.equals("package")) {
6918 readPackageLP(parser);
6919 } else if (tagName.equals("permissions")) {
6920 readPermissionsLP(mPermissions, parser);
6921 } else if (tagName.equals("permission-trees")) {
6922 readPermissionsLP(mPermissionTrees, parser);
6923 } else if (tagName.equals("shared-user")) {
6924 readSharedUserLP(parser);
6925 } else if (tagName.equals("preferred-packages")) {
6926 readPreferredPackagesLP(parser);
6927 } else if (tagName.equals("preferred-activities")) {
6928 readPreferredActivitiesLP(parser);
6929 } else if(tagName.equals("updated-package")) {
6930 readDisabledSysPackageLP(parser);
6931 } else {
6932 Log.w(TAG, "Unknown element under <packages>: "
6933 + parser.getName());
6934 XmlUtils.skipCurrentTag(parser);
6935 }
6936 }
6937
6938 str.close();
6939
6940 } catch(XmlPullParserException e) {
6941 mReadMessages.append("Error reading: " + e.toString());
6942 Log.e(TAG, "Error reading package manager settings", e);
6943
6944 } catch(java.io.IOException e) {
6945 mReadMessages.append("Error reading: " + e.toString());
6946 Log.e(TAG, "Error reading package manager settings", e);
6947
6948 }
6949
6950 int N = mPendingPackages.size();
6951 for (int i=0; i<N; i++) {
6952 final PendingPackage pp = mPendingPackages.get(i);
6953 Object idObj = getUserIdLP(pp.sharedId);
6954 if (idObj != null && idObj instanceof SharedUserSetting) {
6955 PackageSetting p = getPackageLP(pp.name,
6956 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006957 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 if (p == null) {
6959 Log.w(TAG, "Unable to create application package for "
6960 + pp.name);
6961 continue;
6962 }
6963 p.copyFrom(pp);
6964 } else if (idObj != null) {
6965 String msg = "Bad package setting: package " + pp.name
6966 + " has shared uid " + pp.sharedId
6967 + " that is not a shared uid\n";
6968 mReadMessages.append(msg);
6969 Log.e(TAG, msg);
6970 } else {
6971 String msg = "Bad package setting: package " + pp.name
6972 + " has shared uid " + pp.sharedId
6973 + " that is not defined\n";
6974 mReadMessages.append(msg);
6975 Log.e(TAG, msg);
6976 }
6977 }
6978 mPendingPackages.clear();
6979
6980 N = mPendingPreferredPackages.size();
6981 mPreferredPackages.clear();
6982 for (int i=0; i<N; i++) {
6983 final String name = mPendingPreferredPackages.get(i);
6984 final PackageSetting p = mPackages.get(name);
6985 if (p != null) {
6986 mPreferredPackages.add(p);
6987 } else {
6988 Log.w(TAG, "Unknown preferred package: " + name);
6989 }
6990 }
6991 mPendingPreferredPackages.clear();
6992
6993 mReadMessages.append("Read completed successfully: "
6994 + mPackages.size() + " packages, "
6995 + mSharedUsers.size() + " shared uids\n");
6996
6997 return true;
6998 }
6999
7000 private int readInt(XmlPullParser parser, String ns, String name,
7001 int defValue) {
7002 String v = parser.getAttributeValue(ns, name);
7003 try {
7004 if (v == null) {
7005 return defValue;
7006 }
7007 return Integer.parseInt(v);
7008 } catch (NumberFormatException e) {
7009 reportSettingsProblem(Log.WARN,
7010 "Error in package manager settings: attribute " +
7011 name + " has bad integer value " + v + " at "
7012 + parser.getPositionDescription());
7013 }
7014 return defValue;
7015 }
7016
7017 private void readPermissionsLP(HashMap<String, BasePermission> out,
7018 XmlPullParser parser)
7019 throws IOException, XmlPullParserException {
7020 int outerDepth = parser.getDepth();
7021 int type;
7022 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7023 && (type != XmlPullParser.END_TAG
7024 || parser.getDepth() > outerDepth)) {
7025 if (type == XmlPullParser.END_TAG
7026 || type == XmlPullParser.TEXT) {
7027 continue;
7028 }
7029
7030 String tagName = parser.getName();
7031 if (tagName.equals("item")) {
7032 String name = parser.getAttributeValue(null, "name");
7033 String sourcePackage = parser.getAttributeValue(null, "package");
7034 String ptype = parser.getAttributeValue(null, "type");
7035 if (name != null && sourcePackage != null) {
7036 boolean dynamic = "dynamic".equals(ptype);
7037 BasePermission bp = new BasePermission(name, sourcePackage,
7038 dynamic
7039 ? BasePermission.TYPE_DYNAMIC
7040 : BasePermission.TYPE_NORMAL);
7041 if (dynamic) {
7042 PermissionInfo pi = new PermissionInfo();
7043 pi.packageName = sourcePackage.intern();
7044 pi.name = name.intern();
7045 pi.icon = readInt(parser, null, "icon", 0);
7046 pi.nonLocalizedLabel = parser.getAttributeValue(
7047 null, "label");
7048 pi.protectionLevel = readInt(parser, null, "protection",
7049 PermissionInfo.PROTECTION_NORMAL);
7050 bp.pendingInfo = pi;
7051 }
7052 out.put(bp.name, bp);
7053 } else {
7054 reportSettingsProblem(Log.WARN,
7055 "Error in package manager settings: permissions has"
7056 + " no name at " + parser.getPositionDescription());
7057 }
7058 } else {
7059 reportSettingsProblem(Log.WARN,
7060 "Unknown element reading permissions: "
7061 + parser.getName() + " at "
7062 + parser.getPositionDescription());
7063 }
7064 XmlUtils.skipCurrentTag(parser);
7065 }
7066 }
7067
7068 private void readDisabledSysPackageLP(XmlPullParser parser)
7069 throws XmlPullParserException, IOException {
7070 String name = parser.getAttributeValue(null, "name");
7071 String codePathStr = parser.getAttributeValue(null, "codePath");
7072 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
7073 if(resourcePathStr == null) {
7074 resourcePathStr = codePathStr;
7075 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007076 String version = parser.getAttributeValue(null, "version");
7077 int versionCode = 0;
7078 if (version != null) {
7079 try {
7080 versionCode = Integer.parseInt(version);
7081 } catch (NumberFormatException e) {
7082 }
7083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007084
7085 int pkgFlags = 0;
7086 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7087 PackageSetting ps = new PackageSetting(name,
7088 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007089 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007090 String timeStampStr = parser.getAttributeValue(null, "ts");
7091 if (timeStampStr != null) {
7092 try {
7093 long timeStamp = Long.parseLong(timeStampStr);
7094 ps.setTimeStamp(timeStamp, timeStampStr);
7095 } catch (NumberFormatException e) {
7096 }
7097 }
7098 String idStr = parser.getAttributeValue(null, "userId");
7099 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7100 if(ps.userId <= 0) {
7101 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7102 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7103 }
7104 int outerDepth = parser.getDepth();
7105 int type;
7106 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7107 && (type != XmlPullParser.END_TAG
7108 || parser.getDepth() > outerDepth)) {
7109 if (type == XmlPullParser.END_TAG
7110 || type == XmlPullParser.TEXT) {
7111 continue;
7112 }
7113
7114 String tagName = parser.getName();
7115 if (tagName.equals("perms")) {
7116 readGrantedPermissionsLP(parser,
7117 ps.grantedPermissions);
7118 } else {
7119 reportSettingsProblem(Log.WARN,
7120 "Unknown element under <updated-package>: "
7121 + parser.getName());
7122 XmlUtils.skipCurrentTag(parser);
7123 }
7124 }
7125 mDisabledSysPackages.put(name, ps);
7126 }
7127
7128 private void readPackageLP(XmlPullParser parser)
7129 throws XmlPullParserException, IOException {
7130 String name = null;
7131 String idStr = null;
7132 String sharedIdStr = null;
7133 String codePathStr = null;
7134 String resourcePathStr = null;
7135 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007136 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 int pkgFlags = 0;
7138 String timeStampStr;
7139 long timeStamp = 0;
7140 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007141 String version = null;
7142 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 try {
7144 name = parser.getAttributeValue(null, "name");
7145 idStr = parser.getAttributeValue(null, "userId");
7146 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7147 codePathStr = parser.getAttributeValue(null, "codePath");
7148 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007149 version = parser.getAttributeValue(null, "version");
7150 if (version != null) {
7151 try {
7152 versionCode = Integer.parseInt(version);
7153 } catch (NumberFormatException e) {
7154 }
7155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007156 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007157 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 if (systemStr != null) {
7159 if ("true".equals(systemStr)) {
7160 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7161 }
7162 } else {
7163 // Old settings that don't specify system... just treat
7164 // them as system, good enough.
7165 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7166 }
7167 timeStampStr = parser.getAttributeValue(null, "ts");
7168 if (timeStampStr != null) {
7169 try {
7170 timeStamp = Long.parseLong(timeStampStr);
7171 } catch (NumberFormatException e) {
7172 }
7173 }
7174 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7175 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7176 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7177 if (resourcePathStr == null) {
7178 resourcePathStr = codePathStr;
7179 }
7180 if (name == null) {
7181 reportSettingsProblem(Log.WARN,
7182 "Error in package manager settings: <package> has no name at "
7183 + parser.getPositionDescription());
7184 } else if (codePathStr == null) {
7185 reportSettingsProblem(Log.WARN,
7186 "Error in package manager settings: <package> has no codePath at "
7187 + parser.getPositionDescription());
7188 } else if (userId > 0) {
7189 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007190 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007191 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7192 + ": userId=" + userId + " pkg=" + packageSetting);
7193 if (packageSetting == null) {
7194 reportSettingsProblem(Log.ERROR,
7195 "Failure adding uid " + userId
7196 + " while parsing settings at "
7197 + parser.getPositionDescription());
7198 } else {
7199 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7200 }
7201 } else if (sharedIdStr != null) {
7202 userId = sharedIdStr != null
7203 ? Integer.parseInt(sharedIdStr) : 0;
7204 if (userId > 0) {
7205 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007206 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7208 mPendingPackages.add((PendingPackage) packageSetting);
7209 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7210 + ": sharedUserId=" + userId + " pkg="
7211 + packageSetting);
7212 } else {
7213 reportSettingsProblem(Log.WARN,
7214 "Error in package manager settings: package "
7215 + name + " has bad sharedId " + sharedIdStr
7216 + " at " + parser.getPositionDescription());
7217 }
7218 } else {
7219 reportSettingsProblem(Log.WARN,
7220 "Error in package manager settings: package "
7221 + name + " has bad userId " + idStr + " at "
7222 + parser.getPositionDescription());
7223 }
7224 } catch (NumberFormatException e) {
7225 reportSettingsProblem(Log.WARN,
7226 "Error in package manager settings: package "
7227 + name + " has bad userId " + idStr + " at "
7228 + parser.getPositionDescription());
7229 }
7230 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007231 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 final String enabledStr = parser.getAttributeValue(null, "enabled");
7233 if (enabledStr != null) {
7234 if (enabledStr.equalsIgnoreCase("true")) {
7235 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7236 } else if (enabledStr.equalsIgnoreCase("false")) {
7237 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7238 } else if (enabledStr.equalsIgnoreCase("default")) {
7239 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7240 } else {
7241 reportSettingsProblem(Log.WARN,
7242 "Error in package manager settings: package "
7243 + name + " has bad enabled value: " + idStr
7244 + " at " + parser.getPositionDescription());
7245 }
7246 } else {
7247 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7248 }
7249 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7250 if (installStatusStr != null) {
7251 if (installStatusStr.equalsIgnoreCase("false")) {
7252 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7253 } else {
7254 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7255 }
7256 }
7257
7258 int outerDepth = parser.getDepth();
7259 int type;
7260 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7261 && (type != XmlPullParser.END_TAG
7262 || parser.getDepth() > outerDepth)) {
7263 if (type == XmlPullParser.END_TAG
7264 || type == XmlPullParser.TEXT) {
7265 continue;
7266 }
7267
7268 String tagName = parser.getName();
7269 if (tagName.equals("disabled-components")) {
7270 readDisabledComponentsLP(packageSetting, parser);
7271 } else if (tagName.equals("enabled-components")) {
7272 readEnabledComponentsLP(packageSetting, parser);
7273 } else if (tagName.equals("sigs")) {
7274 packageSetting.signatures.readXml(parser, mPastSignatures);
7275 } else if (tagName.equals("perms")) {
7276 readGrantedPermissionsLP(parser,
7277 packageSetting.loadedPermissions);
7278 packageSetting.permissionsFixed = true;
7279 } else {
7280 reportSettingsProblem(Log.WARN,
7281 "Unknown element under <package>: "
7282 + parser.getName());
7283 XmlUtils.skipCurrentTag(parser);
7284 }
7285 }
7286 } else {
7287 XmlUtils.skipCurrentTag(parser);
7288 }
7289 }
7290
7291 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7292 XmlPullParser parser)
7293 throws IOException, XmlPullParserException {
7294 int outerDepth = parser.getDepth();
7295 int type;
7296 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7297 && (type != XmlPullParser.END_TAG
7298 || parser.getDepth() > outerDepth)) {
7299 if (type == XmlPullParser.END_TAG
7300 || type == XmlPullParser.TEXT) {
7301 continue;
7302 }
7303
7304 String tagName = parser.getName();
7305 if (tagName.equals("item")) {
7306 String name = parser.getAttributeValue(null, "name");
7307 if (name != null) {
7308 packageSetting.disabledComponents.add(name.intern());
7309 } else {
7310 reportSettingsProblem(Log.WARN,
7311 "Error in package manager settings: <disabled-components> has"
7312 + " no name at " + parser.getPositionDescription());
7313 }
7314 } else {
7315 reportSettingsProblem(Log.WARN,
7316 "Unknown element under <disabled-components>: "
7317 + parser.getName());
7318 }
7319 XmlUtils.skipCurrentTag(parser);
7320 }
7321 }
7322
7323 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7324 XmlPullParser parser)
7325 throws IOException, XmlPullParserException {
7326 int outerDepth = parser.getDepth();
7327 int type;
7328 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7329 && (type != XmlPullParser.END_TAG
7330 || parser.getDepth() > outerDepth)) {
7331 if (type == XmlPullParser.END_TAG
7332 || type == XmlPullParser.TEXT) {
7333 continue;
7334 }
7335
7336 String tagName = parser.getName();
7337 if (tagName.equals("item")) {
7338 String name = parser.getAttributeValue(null, "name");
7339 if (name != null) {
7340 packageSetting.enabledComponents.add(name.intern());
7341 } else {
7342 reportSettingsProblem(Log.WARN,
7343 "Error in package manager settings: <enabled-components> has"
7344 + " no name at " + parser.getPositionDescription());
7345 }
7346 } else {
7347 reportSettingsProblem(Log.WARN,
7348 "Unknown element under <enabled-components>: "
7349 + parser.getName());
7350 }
7351 XmlUtils.skipCurrentTag(parser);
7352 }
7353 }
7354
7355 private void readSharedUserLP(XmlPullParser parser)
7356 throws XmlPullParserException, IOException {
7357 String name = null;
7358 String idStr = null;
7359 int pkgFlags = 0;
7360 SharedUserSetting su = null;
7361 try {
7362 name = parser.getAttributeValue(null, "name");
7363 idStr = parser.getAttributeValue(null, "userId");
7364 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7365 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7366 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7367 }
7368 if (name == null) {
7369 reportSettingsProblem(Log.WARN,
7370 "Error in package manager settings: <shared-user> has no name at "
7371 + parser.getPositionDescription());
7372 } else if (userId == 0) {
7373 reportSettingsProblem(Log.WARN,
7374 "Error in package manager settings: shared-user "
7375 + name + " has bad userId " + idStr + " at "
7376 + parser.getPositionDescription());
7377 } else {
7378 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7379 reportSettingsProblem(Log.ERROR,
7380 "Occurred while parsing settings at "
7381 + parser.getPositionDescription());
7382 }
7383 }
7384 } catch (NumberFormatException e) {
7385 reportSettingsProblem(Log.WARN,
7386 "Error in package manager settings: package "
7387 + name + " has bad userId " + idStr + " at "
7388 + parser.getPositionDescription());
7389 };
7390
7391 if (su != null) {
7392 int outerDepth = parser.getDepth();
7393 int type;
7394 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7395 && (type != XmlPullParser.END_TAG
7396 || parser.getDepth() > outerDepth)) {
7397 if (type == XmlPullParser.END_TAG
7398 || type == XmlPullParser.TEXT) {
7399 continue;
7400 }
7401
7402 String tagName = parser.getName();
7403 if (tagName.equals("sigs")) {
7404 su.signatures.readXml(parser, mPastSignatures);
7405 } else if (tagName.equals("perms")) {
7406 readGrantedPermissionsLP(parser, su.loadedPermissions);
7407 } else {
7408 reportSettingsProblem(Log.WARN,
7409 "Unknown element under <shared-user>: "
7410 + parser.getName());
7411 XmlUtils.skipCurrentTag(parser);
7412 }
7413 }
7414
7415 } else {
7416 XmlUtils.skipCurrentTag(parser);
7417 }
7418 }
7419
7420 private void readGrantedPermissionsLP(XmlPullParser parser,
7421 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7422 int outerDepth = parser.getDepth();
7423 int type;
7424 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7425 && (type != XmlPullParser.END_TAG
7426 || parser.getDepth() > outerDepth)) {
7427 if (type == XmlPullParser.END_TAG
7428 || type == XmlPullParser.TEXT) {
7429 continue;
7430 }
7431
7432 String tagName = parser.getName();
7433 if (tagName.equals("item")) {
7434 String name = parser.getAttributeValue(null, "name");
7435 if (name != null) {
7436 outPerms.add(name.intern());
7437 } else {
7438 reportSettingsProblem(Log.WARN,
7439 "Error in package manager settings: <perms> has"
7440 + " no name at " + parser.getPositionDescription());
7441 }
7442 } else {
7443 reportSettingsProblem(Log.WARN,
7444 "Unknown element under <perms>: "
7445 + parser.getName());
7446 }
7447 XmlUtils.skipCurrentTag(parser);
7448 }
7449 }
7450
7451 private void readPreferredPackagesLP(XmlPullParser parser)
7452 throws XmlPullParserException, IOException {
7453 int outerDepth = parser.getDepth();
7454 int type;
7455 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7456 && (type != XmlPullParser.END_TAG
7457 || parser.getDepth() > outerDepth)) {
7458 if (type == XmlPullParser.END_TAG
7459 || type == XmlPullParser.TEXT) {
7460 continue;
7461 }
7462
7463 String tagName = parser.getName();
7464 if (tagName.equals("item")) {
7465 String name = parser.getAttributeValue(null, "name");
7466 if (name != null) {
7467 mPendingPreferredPackages.add(name);
7468 } else {
7469 reportSettingsProblem(Log.WARN,
7470 "Error in package manager settings: <preferred-package> has no name at "
7471 + parser.getPositionDescription());
7472 }
7473 } else {
7474 reportSettingsProblem(Log.WARN,
7475 "Unknown element under <preferred-packages>: "
7476 + parser.getName());
7477 }
7478 XmlUtils.skipCurrentTag(parser);
7479 }
7480 }
7481
7482 private void readPreferredActivitiesLP(XmlPullParser parser)
7483 throws XmlPullParserException, IOException {
7484 int outerDepth = parser.getDepth();
7485 int type;
7486 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7487 && (type != XmlPullParser.END_TAG
7488 || parser.getDepth() > outerDepth)) {
7489 if (type == XmlPullParser.END_TAG
7490 || type == XmlPullParser.TEXT) {
7491 continue;
7492 }
7493
7494 String tagName = parser.getName();
7495 if (tagName.equals("item")) {
7496 PreferredActivity pa = new PreferredActivity(parser);
7497 if (pa.mParseError == null) {
7498 mPreferredActivities.addFilter(pa);
7499 } else {
7500 reportSettingsProblem(Log.WARN,
7501 "Error in package manager settings: <preferred-activity> "
7502 + pa.mParseError + " at "
7503 + parser.getPositionDescription());
7504 }
7505 } else {
7506 reportSettingsProblem(Log.WARN,
7507 "Unknown element under <preferred-activities>: "
7508 + parser.getName());
7509 XmlUtils.skipCurrentTag(parser);
7510 }
7511 }
7512 }
7513
7514 // Returns -1 if we could not find an available UserId to assign
7515 private int newUserIdLP(Object obj) {
7516 // Let's be stupidly inefficient for now...
7517 final int N = mUserIds.size();
7518 for (int i=0; i<N; i++) {
7519 if (mUserIds.get(i) == null) {
7520 mUserIds.set(i, obj);
7521 return FIRST_APPLICATION_UID + i;
7522 }
7523 }
7524
7525 // None left?
7526 if (N >= MAX_APPLICATION_UIDS) {
7527 return -1;
7528 }
7529
7530 mUserIds.add(obj);
7531 return FIRST_APPLICATION_UID + N;
7532 }
7533
7534 public PackageSetting getDisabledSystemPkg(String name) {
7535 synchronized(mPackages) {
7536 PackageSetting ps = mDisabledSysPackages.get(name);
7537 return ps;
7538 }
7539 }
7540
7541 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7542 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7543 if (Config.LOGV) {
7544 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7545 + " componentName = " + componentInfo.name);
7546 Log.v(TAG, "enabledComponents: "
7547 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7548 Log.v(TAG, "disabledComponents: "
7549 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7550 }
7551 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7552 || ((componentInfo.enabled
7553 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7554 || (componentInfo.applicationInfo.enabled
7555 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7556 && !packageSettings.disabledComponents.contains(componentInfo.name))
7557 || packageSettings.enabledComponents.contains(componentInfo.name));
7558 }
7559 }
7560}