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