blob: 867f215cc97ea10129d7a0913ccdd9595e9e1e4e [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
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001106 public boolean hasSystemFeature(String name) {
1107 synchronized (mPackages) {
1108 return mAvailableFeatures.containsKey(name);
1109 }
1110 }
1111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 public int checkPermission(String permName, String pkgName) {
1113 synchronized (mPackages) {
1114 PackageParser.Package p = mPackages.get(pkgName);
1115 if (p != null && p.mExtras != null) {
1116 PackageSetting ps = (PackageSetting)p.mExtras;
1117 if (ps.sharedUser != null) {
1118 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1119 return PackageManager.PERMISSION_GRANTED;
1120 }
1121 } else if (ps.grantedPermissions.contains(permName)) {
1122 return PackageManager.PERMISSION_GRANTED;
1123 }
1124 }
1125 }
1126 return PackageManager.PERMISSION_DENIED;
1127 }
1128
1129 public int checkUidPermission(String permName, int uid) {
1130 synchronized (mPackages) {
1131 Object obj = mSettings.getUserIdLP(uid);
1132 if (obj != null) {
1133 if (obj instanceof SharedUserSetting) {
1134 SharedUserSetting sus = (SharedUserSetting)obj;
1135 if (sus.grantedPermissions.contains(permName)) {
1136 return PackageManager.PERMISSION_GRANTED;
1137 }
1138 } else if (obj instanceof PackageSetting) {
1139 PackageSetting ps = (PackageSetting)obj;
1140 if (ps.grantedPermissions.contains(permName)) {
1141 return PackageManager.PERMISSION_GRANTED;
1142 }
1143 }
1144 } else {
1145 HashSet<String> perms = mSystemPermissions.get(uid);
1146 if (perms != null && perms.contains(permName)) {
1147 return PackageManager.PERMISSION_GRANTED;
1148 }
1149 }
1150 }
1151 return PackageManager.PERMISSION_DENIED;
1152 }
1153
1154 private BasePermission findPermissionTreeLP(String permName) {
1155 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1156 if (permName.startsWith(bp.name) &&
1157 permName.length() > bp.name.length() &&
1158 permName.charAt(bp.name.length()) == '.') {
1159 return bp;
1160 }
1161 }
1162 return null;
1163 }
1164
1165 private BasePermission checkPermissionTreeLP(String permName) {
1166 if (permName != null) {
1167 BasePermission bp = findPermissionTreeLP(permName);
1168 if (bp != null) {
1169 if (bp.uid == Binder.getCallingUid()) {
1170 return bp;
1171 }
1172 throw new SecurityException("Calling uid "
1173 + Binder.getCallingUid()
1174 + " is not allowed to add to permission tree "
1175 + bp.name + " owned by uid " + bp.uid);
1176 }
1177 }
1178 throw new SecurityException("No permission tree found for " + permName);
1179 }
1180
1181 public boolean addPermission(PermissionInfo info) {
1182 synchronized (mPackages) {
1183 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1184 throw new SecurityException("Label must be specified in permission");
1185 }
1186 BasePermission tree = checkPermissionTreeLP(info.name);
1187 BasePermission bp = mSettings.mPermissions.get(info.name);
1188 boolean added = bp == null;
1189 if (added) {
1190 bp = new BasePermission(info.name, tree.sourcePackage,
1191 BasePermission.TYPE_DYNAMIC);
1192 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1193 throw new SecurityException(
1194 "Not allowed to modify non-dynamic permission "
1195 + info.name);
1196 }
1197 bp.perm = new PackageParser.Permission(tree.perm.owner,
1198 new PermissionInfo(info));
1199 bp.perm.info.packageName = tree.perm.info.packageName;
1200 bp.uid = tree.uid;
1201 if (added) {
1202 mSettings.mPermissions.put(info.name, bp);
1203 }
1204 mSettings.writeLP();
1205 return added;
1206 }
1207 }
1208
1209 public void removePermission(String name) {
1210 synchronized (mPackages) {
1211 checkPermissionTreeLP(name);
1212 BasePermission bp = mSettings.mPermissions.get(name);
1213 if (bp != null) {
1214 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1215 throw new SecurityException(
1216 "Not allowed to modify non-dynamic permission "
1217 + name);
1218 }
1219 mSettings.mPermissions.remove(name);
1220 mSettings.writeLP();
1221 }
1222 }
1223 }
1224
Dianne Hackborn854060af2009-07-09 18:14:31 -07001225 public boolean isProtectedBroadcast(String actionName) {
1226 synchronized (mPackages) {
1227 return mProtectedBroadcasts.contains(actionName);
1228 }
1229 }
1230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 public int checkSignatures(String pkg1, String pkg2) {
1232 synchronized (mPackages) {
1233 PackageParser.Package p1 = mPackages.get(pkg1);
1234 PackageParser.Package p2 = mPackages.get(pkg2);
1235 if (p1 == null || p1.mExtras == null
1236 || p2 == null || p2.mExtras == null) {
1237 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1238 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001239 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 }
1241 }
1242
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001243 public int checkUidSignatures(int uid1, int uid2) {
1244 synchronized (mPackages) {
1245 Signature[] s1;
1246 Signature[] s2;
1247 Object obj = mSettings.getUserIdLP(uid1);
1248 if (obj != null) {
1249 if (obj instanceof SharedUserSetting) {
1250 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1251 } else if (obj instanceof PackageSetting) {
1252 s1 = ((PackageSetting)obj).signatures.mSignatures;
1253 } else {
1254 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1255 }
1256 } else {
1257 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1258 }
1259 obj = mSettings.getUserIdLP(uid2);
1260 if (obj != null) {
1261 if (obj instanceof SharedUserSetting) {
1262 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1263 } else if (obj instanceof PackageSetting) {
1264 s2 = ((PackageSetting)obj).signatures.mSignatures;
1265 } else {
1266 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1267 }
1268 } else {
1269 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1270 }
1271 return checkSignaturesLP(s1, s2);
1272 }
1273 }
1274
1275 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1276 if (s1 == null) {
1277 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1279 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1280 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001281 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1283 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001284 final int N1 = s1.length;
1285 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 for (int i=0; i<N1; i++) {
1287 boolean match = false;
1288 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001289 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290 match = true;
1291 break;
1292 }
1293 }
1294 if (!match) {
1295 return PackageManager.SIGNATURE_NO_MATCH;
1296 }
1297 }
1298 return PackageManager.SIGNATURE_MATCH;
1299 }
1300
1301 public String[] getPackagesForUid(int uid) {
1302 synchronized (mPackages) {
1303 Object obj = mSettings.getUserIdLP(uid);
1304 if (obj instanceof SharedUserSetting) {
1305 SharedUserSetting sus = (SharedUserSetting)obj;
1306 final int N = sus.packages.size();
1307 String[] res = new String[N];
1308 Iterator<PackageSetting> it = sus.packages.iterator();
1309 int i=0;
1310 while (it.hasNext()) {
1311 res[i++] = it.next().name;
1312 }
1313 return res;
1314 } else if (obj instanceof PackageSetting) {
1315 PackageSetting ps = (PackageSetting)obj;
1316 return new String[] { ps.name };
1317 }
1318 }
1319 return null;
1320 }
1321
1322 public String getNameForUid(int uid) {
1323 synchronized (mPackages) {
1324 Object obj = mSettings.getUserIdLP(uid);
1325 if (obj instanceof SharedUserSetting) {
1326 SharedUserSetting sus = (SharedUserSetting)obj;
1327 return sus.name + ":" + sus.userId;
1328 } else if (obj instanceof PackageSetting) {
1329 PackageSetting ps = (PackageSetting)obj;
1330 return ps.name;
1331 }
1332 }
1333 return null;
1334 }
1335
1336 public int getUidForSharedUser(String sharedUserName) {
1337 if(sharedUserName == null) {
1338 return -1;
1339 }
1340 synchronized (mPackages) {
1341 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1342 if(suid == null) {
1343 return -1;
1344 }
1345 return suid.userId;
1346 }
1347 }
1348
1349 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1350 int flags) {
1351 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001352 return chooseBestActivity(intent, resolvedType, flags, query);
1353 }
1354
Mihai Predaeae850c2009-05-13 10:13:48 +02001355 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1356 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 if (query != null) {
1358 final int N = query.size();
1359 if (N == 1) {
1360 return query.get(0);
1361 } else if (N > 1) {
1362 // If there is more than one activity with the same priority,
1363 // then let the user decide between them.
1364 ResolveInfo r0 = query.get(0);
1365 ResolveInfo r1 = query.get(1);
1366 if (false) {
1367 System.out.println(r0.activityInfo.name +
1368 "=" + r0.priority + " vs " +
1369 r1.activityInfo.name +
1370 "=" + r1.priority);
1371 }
1372 // If the first activity has a higher priority, or a different
1373 // default, then it is always desireable to pick it.
1374 if (r0.priority != r1.priority
1375 || r0.preferredOrder != r1.preferredOrder
1376 || r0.isDefault != r1.isDefault) {
1377 return query.get(0);
1378 }
1379 // If we have saved a preference for a preferred activity for
1380 // this Intent, use that.
1381 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1382 flags, query, r0.priority);
1383 if (ri != null) {
1384 return ri;
1385 }
1386 return mResolveInfo;
1387 }
1388 }
1389 return null;
1390 }
1391
1392 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1393 int flags, List<ResolveInfo> query, int priority) {
1394 synchronized (mPackages) {
1395 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1396 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001397 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1399 if (prefs != null && prefs.size() > 0) {
1400 // First figure out how good the original match set is.
1401 // We will only allow preferred activities that came
1402 // from the same match quality.
1403 int match = 0;
1404 final int N = query.size();
1405 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1406 for (int j=0; j<N; j++) {
1407 ResolveInfo ri = query.get(j);
1408 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1409 + ": 0x" + Integer.toHexString(match));
1410 if (ri.match > match) match = ri.match;
1411 }
1412 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1413 + Integer.toHexString(match));
1414 match &= IntentFilter.MATCH_CATEGORY_MASK;
1415 final int M = prefs.size();
1416 for (int i=0; i<M; i++) {
1417 PreferredActivity pa = prefs.get(i);
1418 if (pa.mMatch != match) {
1419 continue;
1420 }
1421 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1422 if (DEBUG_PREFERRED) {
1423 Log.v(TAG, "Got preferred activity:");
1424 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1425 }
1426 if (ai != null) {
1427 for (int j=0; j<N; j++) {
1428 ResolveInfo ri = query.get(j);
1429 if (!ri.activityInfo.applicationInfo.packageName
1430 .equals(ai.applicationInfo.packageName)) {
1431 continue;
1432 }
1433 if (!ri.activityInfo.name.equals(ai.name)) {
1434 continue;
1435 }
1436
1437 // Okay we found a previously set preferred app.
1438 // If the result set is different from when this
1439 // was created, we need to clear it and re-ask the
1440 // user their preference.
1441 if (!pa.sameSet(query, priority)) {
1442 Log.i(TAG, "Result set changed, dropping preferred activity for "
1443 + intent + " type " + resolvedType);
1444 mSettings.mPreferredActivities.removeFilter(pa);
1445 return null;
1446 }
1447
1448 // Yay!
1449 return ri;
1450 }
1451 }
1452 }
1453 }
1454 }
1455 return null;
1456 }
1457
1458 public List<ResolveInfo> queryIntentActivities(Intent intent,
1459 String resolvedType, int flags) {
1460 ComponentName comp = intent.getComponent();
1461 if (comp != null) {
1462 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1463 ActivityInfo ai = getActivityInfo(comp, flags);
1464 if (ai != null) {
1465 ResolveInfo ri = new ResolveInfo();
1466 ri.activityInfo = ai;
1467 list.add(ri);
1468 }
1469 return list;
1470 }
1471
1472 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001473 String pkgName = intent.getPackage();
1474 if (pkgName == null) {
1475 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1476 resolvedType, flags);
1477 }
1478 PackageParser.Package pkg = mPackages.get(pkgName);
1479 if (pkg != null) {
1480 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1481 resolvedType, flags, pkg.activities);
1482 }
1483 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 }
1485 }
1486
1487 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1488 Intent[] specifics, String[] specificTypes, Intent intent,
1489 String resolvedType, int flags) {
1490 final String resultsAction = intent.getAction();
1491
1492 List<ResolveInfo> results = queryIntentActivities(
1493 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1494 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1495
1496 int specificsPos = 0;
1497 int N;
1498
1499 // todo: note that the algorithm used here is O(N^2). This
1500 // isn't a problem in our current environment, but if we start running
1501 // into situations where we have more than 5 or 10 matches then this
1502 // should probably be changed to something smarter...
1503
1504 // First we go through and resolve each of the specific items
1505 // that were supplied, taking care of removing any corresponding
1506 // duplicate items in the generic resolve list.
1507 if (specifics != null) {
1508 for (int i=0; i<specifics.length; i++) {
1509 final Intent sintent = specifics[i];
1510 if (sintent == null) {
1511 continue;
1512 }
1513
1514 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1515 String action = sintent.getAction();
1516 if (resultsAction != null && resultsAction.equals(action)) {
1517 // If this action was explicitly requested, then don't
1518 // remove things that have it.
1519 action = null;
1520 }
1521 ComponentName comp = sintent.getComponent();
1522 ResolveInfo ri = null;
1523 ActivityInfo ai = null;
1524 if (comp == null) {
1525 ri = resolveIntent(
1526 sintent,
1527 specificTypes != null ? specificTypes[i] : null,
1528 flags);
1529 if (ri == null) {
1530 continue;
1531 }
1532 if (ri == mResolveInfo) {
1533 // ACK! Must do something better with this.
1534 }
1535 ai = ri.activityInfo;
1536 comp = new ComponentName(ai.applicationInfo.packageName,
1537 ai.name);
1538 } else {
1539 ai = getActivityInfo(comp, flags);
1540 if (ai == null) {
1541 continue;
1542 }
1543 }
1544
1545 // Look for any generic query activities that are duplicates
1546 // of this specific one, and remove them from the results.
1547 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1548 N = results.size();
1549 int j;
1550 for (j=specificsPos; j<N; j++) {
1551 ResolveInfo sri = results.get(j);
1552 if ((sri.activityInfo.name.equals(comp.getClassName())
1553 && sri.activityInfo.applicationInfo.packageName.equals(
1554 comp.getPackageName()))
1555 || (action != null && sri.filter.matchAction(action))) {
1556 results.remove(j);
1557 if (Config.LOGV) Log.v(
1558 TAG, "Removing duplicate item from " + j
1559 + " due to specific " + specificsPos);
1560 if (ri == null) {
1561 ri = sri;
1562 }
1563 j--;
1564 N--;
1565 }
1566 }
1567
1568 // Add this specific item to its proper place.
1569 if (ri == null) {
1570 ri = new ResolveInfo();
1571 ri.activityInfo = ai;
1572 }
1573 results.add(specificsPos, ri);
1574 ri.specificIndex = i;
1575 specificsPos++;
1576 }
1577 }
1578
1579 // Now we go through the remaining generic results and remove any
1580 // duplicate actions that are found here.
1581 N = results.size();
1582 for (int i=specificsPos; i<N-1; i++) {
1583 final ResolveInfo rii = results.get(i);
1584 if (rii.filter == null) {
1585 continue;
1586 }
1587
1588 // Iterate over all of the actions of this result's intent
1589 // filter... typically this should be just one.
1590 final Iterator<String> it = rii.filter.actionsIterator();
1591 if (it == null) {
1592 continue;
1593 }
1594 while (it.hasNext()) {
1595 final String action = it.next();
1596 if (resultsAction != null && resultsAction.equals(action)) {
1597 // If this action was explicitly requested, then don't
1598 // remove things that have it.
1599 continue;
1600 }
1601 for (int j=i+1; j<N; j++) {
1602 final ResolveInfo rij = results.get(j);
1603 if (rij.filter != null && rij.filter.hasAction(action)) {
1604 results.remove(j);
1605 if (Config.LOGV) Log.v(
1606 TAG, "Removing duplicate item from " + j
1607 + " due to action " + action + " at " + i);
1608 j--;
1609 N--;
1610 }
1611 }
1612 }
1613
1614 // If the caller didn't request filter information, drop it now
1615 // so we don't have to marshall/unmarshall it.
1616 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1617 rii.filter = null;
1618 }
1619 }
1620
1621 // Filter out the caller activity if so requested.
1622 if (caller != null) {
1623 N = results.size();
1624 for (int i=0; i<N; i++) {
1625 ActivityInfo ainfo = results.get(i).activityInfo;
1626 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1627 && caller.getClassName().equals(ainfo.name)) {
1628 results.remove(i);
1629 break;
1630 }
1631 }
1632 }
1633
1634 // If the caller didn't request filter information,
1635 // drop them now so we don't have to
1636 // marshall/unmarshall it.
1637 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1638 N = results.size();
1639 for (int i=0; i<N; i++) {
1640 results.get(i).filter = null;
1641 }
1642 }
1643
1644 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1645 return results;
1646 }
1647
1648 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1649 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001650 ComponentName comp = intent.getComponent();
1651 if (comp != null) {
1652 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1653 ActivityInfo ai = getReceiverInfo(comp, flags);
1654 if (ai != null) {
1655 ResolveInfo ri = new ResolveInfo();
1656 ri.activityInfo = ai;
1657 list.add(ri);
1658 }
1659 return list;
1660 }
1661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001663 String pkgName = intent.getPackage();
1664 if (pkgName == null) {
1665 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1666 resolvedType, flags);
1667 }
1668 PackageParser.Package pkg = mPackages.get(pkgName);
1669 if (pkg != null) {
1670 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1671 resolvedType, flags, pkg.receivers);
1672 }
1673 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 }
1675 }
1676
1677 public ResolveInfo resolveService(Intent intent, String resolvedType,
1678 int flags) {
1679 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1680 flags);
1681 if (query != null) {
1682 if (query.size() >= 1) {
1683 // If there is more than one service with the same priority,
1684 // just arbitrarily pick the first one.
1685 return query.get(0);
1686 }
1687 }
1688 return null;
1689 }
1690
1691 public List<ResolveInfo> queryIntentServices(Intent intent,
1692 String resolvedType, int flags) {
1693 ComponentName comp = intent.getComponent();
1694 if (comp != null) {
1695 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1696 ServiceInfo si = getServiceInfo(comp, flags);
1697 if (si != null) {
1698 ResolveInfo ri = new ResolveInfo();
1699 ri.serviceInfo = si;
1700 list.add(ri);
1701 }
1702 return list;
1703 }
1704
1705 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001706 String pkgName = intent.getPackage();
1707 if (pkgName == null) {
1708 return (List<ResolveInfo>)mServices.queryIntent(intent,
1709 resolvedType, flags);
1710 }
1711 PackageParser.Package pkg = mPackages.get(pkgName);
1712 if (pkg != null) {
1713 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1714 resolvedType, flags, pkg.services);
1715 }
1716 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 }
1718 }
1719
1720 public List<PackageInfo> getInstalledPackages(int flags) {
1721 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1722
1723 synchronized (mPackages) {
1724 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1725 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1726 while (i.hasNext()) {
1727 final PackageSetting ps = i.next();
1728 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1729 if(psPkg != null) {
1730 finalList.add(psPkg);
1731 }
1732 }
1733 }
1734 else {
1735 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1736 while (i.hasNext()) {
1737 final PackageParser.Package p = i.next();
1738 if (p.applicationInfo != null) {
1739 PackageInfo pi = generatePackageInfo(p, flags);
1740 if(pi != null) {
1741 finalList.add(pi);
1742 }
1743 }
1744 }
1745 }
1746 }
1747 return finalList;
1748 }
1749
1750 public List<ApplicationInfo> getInstalledApplications(int flags) {
1751 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1752 synchronized(mPackages) {
1753 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1754 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1755 while (i.hasNext()) {
1756 final PackageSetting ps = i.next();
1757 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1758 if(ai != null) {
1759 finalList.add(ai);
1760 }
1761 }
1762 }
1763 else {
1764 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1765 while (i.hasNext()) {
1766 final PackageParser.Package p = i.next();
1767 if (p.applicationInfo != null) {
1768 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1769 if(ai != null) {
1770 finalList.add(ai);
1771 }
1772 }
1773 }
1774 }
1775 }
1776 return finalList;
1777 }
1778
1779 public List<ApplicationInfo> getPersistentApplications(int flags) {
1780 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1781
1782 synchronized (mPackages) {
1783 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1784 while (i.hasNext()) {
1785 PackageParser.Package p = i.next();
1786 if (p.applicationInfo != null
1787 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1788 && (!mSafeMode || (p.applicationInfo.flags
1789 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1790 finalList.add(p.applicationInfo);
1791 }
1792 }
1793 }
1794
1795 return finalList;
1796 }
1797
1798 public ProviderInfo resolveContentProvider(String name, int flags) {
1799 synchronized (mPackages) {
1800 final PackageParser.Provider provider = mProviders.get(name);
1801 return provider != null
1802 && mSettings.isEnabledLP(provider.info, flags)
1803 && (!mSafeMode || (provider.info.applicationInfo.flags
1804 &ApplicationInfo.FLAG_SYSTEM) != 0)
1805 ? PackageParser.generateProviderInfo(provider, flags)
1806 : null;
1807 }
1808 }
1809
Fred Quintana718d8a22009-04-29 17:53:20 -07001810 /**
1811 * @deprecated
1812 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 public void querySyncProviders(List outNames, List outInfo) {
1814 synchronized (mPackages) {
1815 Iterator<Map.Entry<String, PackageParser.Provider>> i
1816 = mProviders.entrySet().iterator();
1817
1818 while (i.hasNext()) {
1819 Map.Entry<String, PackageParser.Provider> entry = i.next();
1820 PackageParser.Provider p = entry.getValue();
1821
1822 if (p.syncable
1823 && (!mSafeMode || (p.info.applicationInfo.flags
1824 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1825 outNames.add(entry.getKey());
1826 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1827 }
1828 }
1829 }
1830 }
1831
1832 public List<ProviderInfo> queryContentProviders(String processName,
1833 int uid, int flags) {
1834 ArrayList<ProviderInfo> finalList = null;
1835
1836 synchronized (mPackages) {
1837 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1838 while (i.hasNext()) {
1839 PackageParser.Provider p = i.next();
1840 if (p.info.authority != null
1841 && (processName == null ||
1842 (p.info.processName.equals(processName)
1843 && p.info.applicationInfo.uid == uid))
1844 && mSettings.isEnabledLP(p.info, flags)
1845 && (!mSafeMode || (p.info.applicationInfo.flags
1846 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1847 if (finalList == null) {
1848 finalList = new ArrayList<ProviderInfo>(3);
1849 }
1850 finalList.add(PackageParser.generateProviderInfo(p,
1851 flags));
1852 }
1853 }
1854 }
1855
1856 if (finalList != null) {
1857 Collections.sort(finalList, mProviderInitOrderSorter);
1858 }
1859
1860 return finalList;
1861 }
1862
1863 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1864 int flags) {
1865 synchronized (mPackages) {
1866 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1867 return PackageParser.generateInstrumentationInfo(i, flags);
1868 }
1869 }
1870
1871 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1872 int flags) {
1873 ArrayList<InstrumentationInfo> finalList =
1874 new ArrayList<InstrumentationInfo>();
1875
1876 synchronized (mPackages) {
1877 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1878 while (i.hasNext()) {
1879 PackageParser.Instrumentation p = i.next();
1880 if (targetPackage == null
1881 || targetPackage.equals(p.info.targetPackage)) {
1882 finalList.add(PackageParser.generateInstrumentationInfo(p,
1883 flags));
1884 }
1885 }
1886 }
1887
1888 return finalList;
1889 }
1890
1891 private void scanDirLI(File dir, int flags, int scanMode) {
1892 Log.d(TAG, "Scanning app dir " + dir);
1893
1894 String[] files = dir.list();
1895
1896 int i;
1897 for (i=0; i<files.length; i++) {
1898 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001899 File resFile = file;
1900 // Pick up the resource path from settings for fwd locked apps
1901 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1902 resFile = null;
1903 }
1904 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1906 }
1907 }
1908
1909 private static void reportSettingsProblem(int priority, String msg) {
1910 try {
1911 File dataDir = Environment.getDataDirectory();
1912 File systemDir = new File(dataDir, "system");
1913 File fname = new File(systemDir, "uiderrors.txt");
1914 FileOutputStream out = new FileOutputStream(fname, true);
1915 PrintWriter pw = new PrintWriter(out);
1916 pw.println(msg);
1917 pw.close();
1918 FileUtils.setPermissions(
1919 fname.toString(),
1920 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1921 -1, -1);
1922 } catch (java.io.IOException e) {
1923 }
1924 Log.println(priority, TAG, msg);
1925 }
1926
1927 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1928 PackageParser.Package pkg, File srcFile, int parseFlags) {
1929 if (GET_CERTIFICATES) {
1930 if (ps == null || !ps.codePath.equals(srcFile)
1931 || ps.getTimeStamp() != srcFile.lastModified()) {
1932 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1933 if (!pp.collectCertificates(pkg, parseFlags)) {
1934 mLastScanError = pp.getParseError();
1935 return false;
1936 }
1937 }
1938 }
1939 return true;
1940 }
1941
1942 /*
1943 * Scan a package and return the newly parsed package.
1944 * Returns null in case of errors and the error code is stored in mLastScanError
1945 */
1946 private PackageParser.Package scanPackageLI(File scanFile,
1947 File destCodeFile, File destResourceFile, int parseFlags,
1948 int scanMode) {
1949 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1950 parseFlags |= mDefParseFlags;
1951 PackageParser pp = new PackageParser(scanFile.getPath());
1952 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07001953 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 final PackageParser.Package pkg = pp.parsePackage(scanFile,
1955 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
1956 if (pkg == null) {
1957 mLastScanError = pp.getParseError();
1958 return null;
1959 }
1960 PackageSetting ps;
1961 PackageSetting updatedPkg;
1962 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001963 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
1965 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07001966 // Verify certificates first
1967 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
1968 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
1969 return null;
1970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 if (updatedPkg != null) {
1972 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
1973 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
1974 }
1975 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1976 // Check for updated system applications here
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001977 if (updatedPkg != null) {
1978 if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
1979 if (pkg.mVersionCode <= ps.versionCode) {
1980 // The system package has been updated and the code path does not match
1981 // Ignore entry. Just return
1982 Log.w(TAG, "Package:" + pkg.packageName +
1983 " has been updated. Ignoring the one from path:"+scanFile);
1984 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1985 return null;
1986 } else {
1987 // Delete the older apk pointed to by ps
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07001988 // At this point, its safely assumed that package installation for
1989 // apps in system partition will go through. If not there won't be a working
1990 // version of the app
1991 synchronized (mPackages) {
1992 // Just remove the loaded entries from package lists.
1993 mPackages.remove(ps.name);
1994 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001995 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
1996 mSettings.enableSystemPackageLP(ps.name);
1997 }
1998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 }
2000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 // The apk is forward locked (not public) if its code and resources
2002 // are kept in different files.
2003 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2004 scanMode |= SCAN_FORWARD_LOCKED;
2005 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002006 File resFile = destResourceFile;
2007 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
2008 resFile = getFwdLockedResource(ps.name);
2009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002011 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002012 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2013 }
2014
2015 private static String fixProcessName(String defProcessName,
2016 String processName, int uid) {
2017 if (processName == null) {
2018 return defProcessName;
2019 }
2020 return processName;
2021 }
2022
2023 private boolean verifySignaturesLP(PackageSetting pkgSetting,
2024 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2025 if (pkg.mSignatures != null) {
2026 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2027 updateSignature)) {
2028 Log.e(TAG, "Package " + pkg.packageName
2029 + " signatures do not match the previously installed version; ignoring!");
2030 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2031 return false;
2032 }
2033
2034 if (pkgSetting.sharedUser != null) {
2035 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2036 pkg.mSignatures, updateSignature)) {
2037 Log.e(TAG, "Package " + pkg.packageName
2038 + " has no signatures that match those in shared user "
2039 + pkgSetting.sharedUser.name + "; ignoring!");
2040 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2041 return false;
2042 }
2043 }
2044 } else {
2045 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2046 }
2047 return true;
2048 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002049
2050 public boolean performDexOpt(String packageName) {
2051 if (!mNoDexOpt) {
2052 return false;
2053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002055 PackageParser.Package p;
2056 synchronized (mPackages) {
2057 p = mPackages.get(packageName);
2058 if (p == null || p.mDidDexOpt) {
2059 return false;
2060 }
2061 }
2062 synchronized (mInstallLock) {
2063 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2064 }
2065 }
2066
2067 static final int DEX_OPT_SKIPPED = 0;
2068 static final int DEX_OPT_PERFORMED = 1;
2069 static final int DEX_OPT_FAILED = -1;
2070
2071 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2072 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002073 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002074 String path = pkg.mScanPath;
2075 int ret = 0;
2076 try {
2077 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2078 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2079 !pkg.mForwardLocked);
2080 pkg.mDidDexOpt = true;
2081 performed = true;
2082 }
2083 } catch (FileNotFoundException e) {
2084 Log.w(TAG, "Apk not found for dexopt: " + path);
2085 ret = -1;
2086 } catch (IOException e) {
2087 Log.w(TAG, "Exception reading apk: " + path, e);
2088 ret = -1;
2089 }
2090 if (ret < 0) {
2091 //error from installer
2092 return DEX_OPT_FAILED;
2093 }
2094 }
2095
2096 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2097 }
2098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 private PackageParser.Package scanPackageLI(
2100 File scanFile, File destCodeFile, File destResourceFile,
2101 PackageParser.Package pkg, int parseFlags, int scanMode) {
2102
2103 mScanningPath = scanFile;
2104 if (pkg == null) {
2105 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2106 return null;
2107 }
2108
2109 final String pkgName = pkg.applicationInfo.packageName;
2110 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2111 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2112 }
2113
2114 if (pkgName.equals("android")) {
2115 synchronized (mPackages) {
2116 if (mAndroidApplication != null) {
2117 Log.w(TAG, "*************************************************");
2118 Log.w(TAG, "Core android package being redefined. Skipping.");
2119 Log.w(TAG, " file=" + mScanningPath);
2120 Log.w(TAG, "*************************************************");
2121 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2122 return null;
2123 }
2124
2125 // Set up information for our fall-back user intent resolution
2126 // activity.
2127 mPlatformPackage = pkg;
2128 pkg.mVersionCode = mSdkVersion;
2129 mAndroidApplication = pkg.applicationInfo;
2130 mResolveActivity.applicationInfo = mAndroidApplication;
2131 mResolveActivity.name = ResolverActivity.class.getName();
2132 mResolveActivity.packageName = mAndroidApplication.packageName;
2133 mResolveActivity.processName = mAndroidApplication.processName;
2134 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2135 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2136 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2137 mResolveActivity.exported = true;
2138 mResolveActivity.enabled = true;
2139 mResolveInfo.activityInfo = mResolveActivity;
2140 mResolveInfo.priority = 0;
2141 mResolveInfo.preferredOrder = 0;
2142 mResolveInfo.match = 0;
2143 mResolveComponentName = new ComponentName(
2144 mAndroidApplication.packageName, mResolveActivity.name);
2145 }
2146 }
2147
2148 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2149 TAG, "Scanning package " + pkgName);
2150 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2151 Log.w(TAG, "*************************************************");
2152 Log.w(TAG, "Application package " + pkgName
2153 + " already installed. Skipping duplicate.");
2154 Log.w(TAG, "*************************************************");
2155 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2156 return null;
2157 }
2158
2159 SharedUserSetting suid = null;
2160 PackageSetting pkgSetting = null;
2161
2162 boolean removeExisting = false;
2163
2164 synchronized (mPackages) {
2165 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002166 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2167 if (mTmpSharedLibraries == null ||
2168 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2169 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2170 }
2171 int num = 0;
2172 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2173 for (int i=0; i<N; i++) {
2174 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 if (file == null) {
2176 Log.e(TAG, "Package " + pkg.packageName
2177 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002178 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2180 return null;
2181 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002182 mTmpSharedLibraries[num] = file;
2183 num++;
2184 }
2185 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2186 for (int i=0; i<N; i++) {
2187 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2188 if (file == null) {
2189 Log.w(TAG, "Package " + pkg.packageName
2190 + " desires unavailable shared library "
2191 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2192 } else {
2193 mTmpSharedLibraries[num] = file;
2194 num++;
2195 }
2196 }
2197 if (num > 0) {
2198 pkg.usesLibraryFiles = new String[num];
2199 System.arraycopy(mTmpSharedLibraries, 0,
2200 pkg.usesLibraryFiles, 0, num);
2201 }
2202
2203 if (pkg.reqFeatures != null) {
2204 N = pkg.reqFeatures.size();
2205 for (int i=0; i<N; i++) {
2206 FeatureInfo fi = pkg.reqFeatures.get(i);
2207 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2208 // Don't care.
2209 continue;
2210 }
2211
2212 if (fi.name != null) {
2213 if (mAvailableFeatures.get(fi.name) == null) {
2214 Log.e(TAG, "Package " + pkg.packageName
2215 + " requires unavailable feature "
2216 + fi.name + "; failing!");
2217 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2218 return null;
2219 }
2220 }
2221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 }
2223 }
2224
2225 if (pkg.mSharedUserId != null) {
2226 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2227 pkg.applicationInfo.flags, true);
2228 if (suid == null) {
2229 Log.w(TAG, "Creating application package " + pkgName
2230 + " for shared user failed");
2231 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2232 return null;
2233 }
2234 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2235 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2236 + suid.userId + "): packages=" + suid.packages);
2237 }
2238 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002239
2240 // Just create the setting, don't add it yet. For already existing packages
2241 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2243 destResourceFile, pkg.applicationInfo.flags, true, false);
2244 if (pkgSetting == null) {
2245 Log.w(TAG, "Creating application package " + pkgName + " failed");
2246 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2247 return null;
2248 }
2249 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2250 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2251 }
2252
2253 pkg.applicationInfo.uid = pkgSetting.userId;
2254 pkg.mExtras = pkgSetting;
2255
2256 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
2257 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2258 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2259 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2260 return null;
2261 }
2262 // The signature has changed, but this package is in the system
2263 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002264 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 // However... if this package is part of a shared user, but it
2266 // doesn't match the signature of the shared user, let's fail.
2267 // What this means is that you can't change the signatures
2268 // associated with an overall shared user, which doesn't seem all
2269 // that unreasonable.
2270 if (pkgSetting.sharedUser != null) {
2271 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2272 pkg.mSignatures, false)) {
2273 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2274 return null;
2275 }
2276 }
2277 removeExisting = true;
2278 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002279
2280 // Verify that this new package doesn't have any content providers
2281 // that conflict with existing packages. Only do this if the
2282 // package isn't already installed, since we don't want to break
2283 // things that are installed.
2284 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2285 int N = pkg.providers.size();
2286 int i;
2287 for (i=0; i<N; i++) {
2288 PackageParser.Provider p = pkg.providers.get(i);
2289 String names[] = p.info.authority.split(";");
2290 for (int j = 0; j < names.length; j++) {
2291 if (mProviders.containsKey(names[j])) {
2292 PackageParser.Provider other = mProviders.get(names[j]);
2293 Log.w(TAG, "Can't install because provider name " + names[j] +
2294 " (in package " + pkg.applicationInfo.packageName +
2295 ") is already used by "
2296 + ((other != null && other.component != null)
2297 ? other.component.getPackageName() : "?"));
2298 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2299 return null;
2300 }
2301 }
2302 }
2303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 }
2305
2306 if (removeExisting) {
2307 if (mInstaller != null) {
2308 int ret = mInstaller.remove(pkgName);
2309 if (ret != 0) {
2310 String msg = "System package " + pkg.packageName
2311 + " could not have data directory erased after signature change.";
2312 reportSettingsProblem(Log.WARN, msg);
2313 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2314 return null;
2315 }
2316 }
2317 Log.w(TAG, "System package " + pkg.packageName
2318 + " signature changed: existing data removed.");
2319 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2320 }
2321
2322 long scanFileTime = scanFile.lastModified();
2323 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2324 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2325 pkg.applicationInfo.processName = fixProcessName(
2326 pkg.applicationInfo.packageName,
2327 pkg.applicationInfo.processName,
2328 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002329 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330
2331 File dataPath;
2332 if (mPlatformPackage == pkg) {
2333 // The system package is special.
2334 dataPath = new File (Environment.getDataDirectory(), "system");
2335 pkg.applicationInfo.dataDir = dataPath.getPath();
2336 } else {
2337 // This is a normal package, need to make its data directory.
2338 dataPath = new File(mAppDataDir, pkgName);
2339 if (dataPath.exists()) {
2340 mOutPermissions[1] = 0;
2341 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2342 if (mOutPermissions[1] == pkg.applicationInfo.uid
2343 || !Process.supportsProcesses()) {
2344 pkg.applicationInfo.dataDir = dataPath.getPath();
2345 } else {
2346 boolean recovered = false;
2347 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2348 // If this is a system app, we can at least delete its
2349 // current data so the application will still work.
2350 if (mInstaller != null) {
2351 int ret = mInstaller.remove(pkgName);
2352 if(ret >= 0) {
2353 // Old data gone!
2354 String msg = "System package " + pkg.packageName
2355 + " has changed from uid: "
2356 + mOutPermissions[1] + " to "
2357 + pkg.applicationInfo.uid + "; old data erased";
2358 reportSettingsProblem(Log.WARN, msg);
2359 recovered = true;
2360
2361 // And now re-install the app.
2362 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2363 pkg.applicationInfo.uid);
2364 if (ret == -1) {
2365 // Ack should not happen!
2366 msg = "System package " + pkg.packageName
2367 + " could not have data directory re-created after delete.";
2368 reportSettingsProblem(Log.WARN, msg);
2369 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2370 return null;
2371 }
2372 }
2373 }
2374 if (!recovered) {
2375 mHasSystemUidErrors = true;
2376 }
2377 }
2378 if (!recovered) {
2379 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2380 + pkg.applicationInfo.uid + "/fs_"
2381 + mOutPermissions[1];
2382 String msg = "Package " + pkg.packageName
2383 + " has mismatched uid: "
2384 + mOutPermissions[1] + " on disk, "
2385 + pkg.applicationInfo.uid + " in settings";
2386 synchronized (mPackages) {
2387 if (!mReportedUidError) {
2388 mReportedUidError = true;
2389 msg = msg + "; read messages:\n"
2390 + mSettings.getReadMessagesLP();
2391 }
2392 reportSettingsProblem(Log.ERROR, msg);
2393 }
2394 }
2395 }
2396 pkg.applicationInfo.dataDir = dataPath.getPath();
2397 } else {
2398 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2399 Log.v(TAG, "Want this data dir: " + dataPath);
2400 //invoke installer to do the actual installation
2401 if (mInstaller != null) {
2402 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2403 pkg.applicationInfo.uid);
2404 if(ret < 0) {
2405 // Error from installer
2406 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2407 return null;
2408 }
2409 } else {
2410 dataPath.mkdirs();
2411 if (dataPath.exists()) {
2412 FileUtils.setPermissions(
2413 dataPath.toString(),
2414 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2415 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2416 }
2417 }
2418 if (dataPath.exists()) {
2419 pkg.applicationInfo.dataDir = dataPath.getPath();
2420 } else {
2421 Log.w(TAG, "Unable to create data directory: " + dataPath);
2422 pkg.applicationInfo.dataDir = null;
2423 }
2424 }
2425 }
2426
2427 // Perform shared library installation and dex validation and
2428 // optimization, if this is not a system app.
2429 if (mInstaller != null) {
2430 String path = scanFile.getPath();
2431 if (scanFileNewer) {
2432 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002433 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2434 if (err != PackageManager.INSTALL_SUCCEEDED) {
2435 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 return null;
2437 }
2438 }
2439
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002440 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2441 pkg.mScanPath = path;
2442
2443 if ((scanMode&SCAN_NO_DEX) == 0) {
2444 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2446 return null;
2447 }
2448 }
2449 }
2450
2451 if (mFactoryTest && pkg.requestedPermissions.contains(
2452 android.Manifest.permission.FACTORY_TEST)) {
2453 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2454 }
2455
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002456 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 if ((scanMode&SCAN_MONITOR) != 0) {
2458 pkg.mPath = destCodeFile.getAbsolutePath();
2459 mAppDirs.put(pkg.mPath, pkg);
2460 }
2461
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002462 // Request the ActivityManager to kill the process(only for existing packages)
2463 // so that we do not end up in a confused state while the user is still using the older
2464 // version of the application while the new one gets installed.
2465 IActivityManager am = ActivityManagerNative.getDefault();
2466 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2467 try {
2468 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2469 pkg.applicationInfo.uid);
2470 } catch (RemoteException e) {
2471 }
2472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002475 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002477 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 int N = pkg.providers.size();
2479 StringBuilder r = null;
2480 int i;
2481 for (i=0; i<N; i++) {
2482 PackageParser.Provider p = pkg.providers.get(i);
2483 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2484 p.info.processName, pkg.applicationInfo.uid);
2485 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2486 p.info.name), p);
2487 p.syncable = p.info.isSyncable;
2488 String names[] = p.info.authority.split(";");
2489 p.info.authority = null;
2490 for (int j = 0; j < names.length; j++) {
2491 if (j == 1 && p.syncable) {
2492 // We only want the first authority for a provider to possibly be
2493 // syncable, so if we already added this provider using a different
2494 // authority clear the syncable flag. We copy the provider before
2495 // changing it because the mProviders object contains a reference
2496 // to a provider that we don't want to change.
2497 // Only do this for the second authority since the resulting provider
2498 // object can be the same for all future authorities for this provider.
2499 p = new PackageParser.Provider(p);
2500 p.syncable = false;
2501 }
2502 if (!mProviders.containsKey(names[j])) {
2503 mProviders.put(names[j], p);
2504 if (p.info.authority == null) {
2505 p.info.authority = names[j];
2506 } else {
2507 p.info.authority = p.info.authority + ";" + names[j];
2508 }
2509 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2510 Log.d(TAG, "Registered content provider: " + names[j] +
2511 ", className = " + p.info.name +
2512 ", isSyncable = " + p.info.isSyncable);
2513 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002514 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 Log.w(TAG, "Skipping provider name " + names[j] +
2516 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002517 "): name already used by "
2518 + ((other != null && other.component != null)
2519 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 }
2521 }
2522 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2523 if (r == null) {
2524 r = new StringBuilder(256);
2525 } else {
2526 r.append(' ');
2527 }
2528 r.append(p.info.name);
2529 }
2530 }
2531 if (r != null) {
2532 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2533 }
2534
2535 N = pkg.services.size();
2536 r = null;
2537 for (i=0; i<N; i++) {
2538 PackageParser.Service s = pkg.services.get(i);
2539 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2540 s.info.processName, pkg.applicationInfo.uid);
2541 mServices.addService(s);
2542 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2543 if (r == null) {
2544 r = new StringBuilder(256);
2545 } else {
2546 r.append(' ');
2547 }
2548 r.append(s.info.name);
2549 }
2550 }
2551 if (r != null) {
2552 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2553 }
2554
2555 N = pkg.receivers.size();
2556 r = null;
2557 for (i=0; i<N; i++) {
2558 PackageParser.Activity a = pkg.receivers.get(i);
2559 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2560 a.info.processName, pkg.applicationInfo.uid);
2561 mReceivers.addActivity(a, "receiver");
2562 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2563 if (r == null) {
2564 r = new StringBuilder(256);
2565 } else {
2566 r.append(' ');
2567 }
2568 r.append(a.info.name);
2569 }
2570 }
2571 if (r != null) {
2572 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2573 }
2574
2575 N = pkg.activities.size();
2576 r = null;
2577 for (i=0; i<N; i++) {
2578 PackageParser.Activity a = pkg.activities.get(i);
2579 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2580 a.info.processName, pkg.applicationInfo.uid);
2581 mActivities.addActivity(a, "activity");
2582 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2583 if (r == null) {
2584 r = new StringBuilder(256);
2585 } else {
2586 r.append(' ');
2587 }
2588 r.append(a.info.name);
2589 }
2590 }
2591 if (r != null) {
2592 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2593 }
2594
2595 N = pkg.permissionGroups.size();
2596 r = null;
2597 for (i=0; i<N; i++) {
2598 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2599 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2600 if (cur == null) {
2601 mPermissionGroups.put(pg.info.name, pg);
2602 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2603 if (r == null) {
2604 r = new StringBuilder(256);
2605 } else {
2606 r.append(' ');
2607 }
2608 r.append(pg.info.name);
2609 }
2610 } else {
2611 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2612 + pg.info.packageName + " ignored: original from "
2613 + cur.info.packageName);
2614 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2615 if (r == null) {
2616 r = new StringBuilder(256);
2617 } else {
2618 r.append(' ');
2619 }
2620 r.append("DUP:");
2621 r.append(pg.info.name);
2622 }
2623 }
2624 }
2625 if (r != null) {
2626 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2627 }
2628
2629 N = pkg.permissions.size();
2630 r = null;
2631 for (i=0; i<N; i++) {
2632 PackageParser.Permission p = pkg.permissions.get(i);
2633 HashMap<String, BasePermission> permissionMap =
2634 p.tree ? mSettings.mPermissionTrees
2635 : mSettings.mPermissions;
2636 p.group = mPermissionGroups.get(p.info.group);
2637 if (p.info.group == null || p.group != null) {
2638 BasePermission bp = permissionMap.get(p.info.name);
2639 if (bp == null) {
2640 bp = new BasePermission(p.info.name, p.info.packageName,
2641 BasePermission.TYPE_NORMAL);
2642 permissionMap.put(p.info.name, bp);
2643 }
2644 if (bp.perm == null) {
2645 if (bp.sourcePackage == null
2646 || bp.sourcePackage.equals(p.info.packageName)) {
2647 BasePermission tree = findPermissionTreeLP(p.info.name);
2648 if (tree == null
2649 || tree.sourcePackage.equals(p.info.packageName)) {
2650 bp.perm = p;
2651 bp.uid = pkg.applicationInfo.uid;
2652 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2653 if (r == null) {
2654 r = new StringBuilder(256);
2655 } else {
2656 r.append(' ');
2657 }
2658 r.append(p.info.name);
2659 }
2660 } else {
2661 Log.w(TAG, "Permission " + p.info.name + " from package "
2662 + p.info.packageName + " ignored: base tree "
2663 + tree.name + " is from package "
2664 + tree.sourcePackage);
2665 }
2666 } else {
2667 Log.w(TAG, "Permission " + p.info.name + " from package "
2668 + p.info.packageName + " ignored: original from "
2669 + bp.sourcePackage);
2670 }
2671 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2672 if (r == null) {
2673 r = new StringBuilder(256);
2674 } else {
2675 r.append(' ');
2676 }
2677 r.append("DUP:");
2678 r.append(p.info.name);
2679 }
2680 } else {
2681 Log.w(TAG, "Permission " + p.info.name + " from package "
2682 + p.info.packageName + " ignored: no group "
2683 + p.group);
2684 }
2685 }
2686 if (r != null) {
2687 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2688 }
2689
2690 N = pkg.instrumentation.size();
2691 r = null;
2692 for (i=0; i<N; i++) {
2693 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2694 a.info.packageName = pkg.applicationInfo.packageName;
2695 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2696 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2697 a.info.dataDir = pkg.applicationInfo.dataDir;
2698 mInstrumentation.put(a.component, a);
2699 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2700 if (r == null) {
2701 r = new StringBuilder(256);
2702 } else {
2703 r.append(' ');
2704 }
2705 r.append(a.info.name);
2706 }
2707 }
2708 if (r != null) {
2709 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2710 }
2711
Dianne Hackborn854060af2009-07-09 18:14:31 -07002712 if (pkg.protectedBroadcasts != null) {
2713 N = pkg.protectedBroadcasts.size();
2714 for (i=0; i<N; i++) {
2715 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2716 }
2717 }
2718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 pkgSetting.setTimeStamp(scanFileTime);
2720 }
2721
2722 return pkg;
2723 }
2724
Dianne Hackbornb1811182009-05-21 15:45:42 -07002725 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2726 File dataPath, File scanFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002728 final String sharedLibraryABI = Build.CPU_ABI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2730 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2731 final String sharedLibrarySuffix = ".so";
Dianne Hackbornb1811182009-05-21 15:45:42 -07002732 boolean hasNativeCode = false;
2733 boolean installedNativeCode = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 try {
2735 ZipFile zipFile = new ZipFile(scanFile);
2736 Enumeration<ZipEntry> entries =
2737 (Enumeration<ZipEntry>) zipFile.entries();
2738
2739 while (entries.hasMoreElements()) {
2740 ZipEntry entry = entries.nextElement();
2741 if (entry.isDirectory()) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002742 if (!hasNativeCode && entry.getName().startsWith("lib")) {
2743 hasNativeCode = true;
2744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 continue;
2746 }
2747 String entryName = entry.getName();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002748 if (entryName.startsWith("lib/")) {
2749 hasNativeCode = true;
2750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2752 && entryName.endsWith(sharedLibrarySuffix))) {
2753 continue;
2754 }
2755 String libFileName = entryName.substring(
2756 apkLibraryDirectory.length());
2757 if (libFileName.contains("/")
2758 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2759 continue;
2760 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002761
2762 installedNativeCode = true;
2763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2765 File.separator + libFileName;
2766 File sharedLibraryFile = new File(sharedLibraryFilePath);
2767 if (! sharedLibraryFile.exists() ||
2768 sharedLibraryFile.length() != entry.getSize() ||
2769 sharedLibraryFile.lastModified() != entry.getTime()) {
2770 if (Config.LOGD) {
2771 Log.d(TAG, "Caching shared lib " + entry.getName());
2772 }
2773 if (mInstaller == null) {
2774 sharedLibraryDir.mkdir();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 }
2776 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2777 sharedLibraryFile);
2778 }
2779 }
2780 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002781 Log.w(TAG, "Failed to cache package shared libs", e);
2782 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002784
2785 if (hasNativeCode && !installedNativeCode) {
2786 Log.w(TAG, "Install failed: .apk has native code but none for arch "
2787 + Build.CPU_ABI);
2788 return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
2789 }
2790
2791 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 }
2793
2794 private void cacheSharedLibLI(PackageParser.Package pkg,
2795 ZipFile zipFile, ZipEntry entry,
2796 File sharedLibraryDir,
2797 File sharedLibraryFile) throws IOException {
2798 InputStream inputStream = zipFile.getInputStream(entry);
2799 try {
2800 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2801 String tempFilePath = tempFile.getPath();
2802 // XXX package manager can't change owner, so the lib files for
2803 // now need to be left as world readable and owned by the system.
2804 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2805 ! tempFile.setLastModified(entry.getTime()) ||
2806 FileUtils.setPermissions(tempFilePath,
2807 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2808 |FileUtils.S_IROTH, -1, -1) != 0 ||
2809 ! tempFile.renameTo(sharedLibraryFile)) {
2810 // Failed to properly write file.
2811 tempFile.delete();
2812 throw new IOException("Couldn't create cached shared lib "
2813 + sharedLibraryFile + " in " + sharedLibraryDir);
2814 }
2815 } finally {
2816 inputStream.close();
2817 }
2818 }
2819
2820 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2821 if (chatty && Config.LOGD) Log.d(
2822 TAG, "Removing package " + pkg.applicationInfo.packageName );
2823
2824 synchronized (mPackages) {
2825 if (pkg.mPreferredOrder > 0) {
2826 mSettings.mPreferredPackages.remove(pkg);
2827 pkg.mPreferredOrder = 0;
2828 updatePreferredIndicesLP();
2829 }
2830
2831 clearPackagePreferredActivitiesLP(pkg.packageName);
2832
2833 mPackages.remove(pkg.applicationInfo.packageName);
2834 if (pkg.mPath != null) {
2835 mAppDirs.remove(pkg.mPath);
2836 }
2837
2838 PackageSetting ps = (PackageSetting)pkg.mExtras;
2839 if (ps != null && ps.sharedUser != null) {
2840 // XXX don't do this until the data is removed.
2841 if (false) {
2842 ps.sharedUser.packages.remove(ps);
2843 if (ps.sharedUser.packages.size() == 0) {
2844 // Remove.
2845 }
2846 }
2847 }
2848
2849 int N = pkg.providers.size();
2850 StringBuilder r = null;
2851 int i;
2852 for (i=0; i<N; i++) {
2853 PackageParser.Provider p = pkg.providers.get(i);
2854 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2855 p.info.name));
2856 if (p.info.authority == null) {
2857
2858 /* The is another ContentProvider with this authority when
2859 * this app was installed so this authority is null,
2860 * Ignore it as we don't have to unregister the provider.
2861 */
2862 continue;
2863 }
2864 String names[] = p.info.authority.split(";");
2865 for (int j = 0; j < names.length; j++) {
2866 if (mProviders.get(names[j]) == p) {
2867 mProviders.remove(names[j]);
2868 if (chatty && Config.LOGD) Log.d(
2869 TAG, "Unregistered content provider: " + names[j] +
2870 ", className = " + p.info.name +
2871 ", isSyncable = " + p.info.isSyncable);
2872 }
2873 }
2874 if (chatty) {
2875 if (r == null) {
2876 r = new StringBuilder(256);
2877 } else {
2878 r.append(' ');
2879 }
2880 r.append(p.info.name);
2881 }
2882 }
2883 if (r != null) {
2884 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2885 }
2886
2887 N = pkg.services.size();
2888 r = null;
2889 for (i=0; i<N; i++) {
2890 PackageParser.Service s = pkg.services.get(i);
2891 mServices.removeService(s);
2892 if (chatty) {
2893 if (r == null) {
2894 r = new StringBuilder(256);
2895 } else {
2896 r.append(' ');
2897 }
2898 r.append(s.info.name);
2899 }
2900 }
2901 if (r != null) {
2902 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2903 }
2904
2905 N = pkg.receivers.size();
2906 r = null;
2907 for (i=0; i<N; i++) {
2908 PackageParser.Activity a = pkg.receivers.get(i);
2909 mReceivers.removeActivity(a, "receiver");
2910 if (chatty) {
2911 if (r == null) {
2912 r = new StringBuilder(256);
2913 } else {
2914 r.append(' ');
2915 }
2916 r.append(a.info.name);
2917 }
2918 }
2919 if (r != null) {
2920 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2921 }
2922
2923 N = pkg.activities.size();
2924 r = null;
2925 for (i=0; i<N; i++) {
2926 PackageParser.Activity a = pkg.activities.get(i);
2927 mActivities.removeActivity(a, "activity");
2928 if (chatty) {
2929 if (r == null) {
2930 r = new StringBuilder(256);
2931 } else {
2932 r.append(' ');
2933 }
2934 r.append(a.info.name);
2935 }
2936 }
2937 if (r != null) {
2938 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2939 }
2940
2941 N = pkg.permissions.size();
2942 r = null;
2943 for (i=0; i<N; i++) {
2944 PackageParser.Permission p = pkg.permissions.get(i);
2945 boolean tree = false;
2946 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2947 if (bp == null) {
2948 tree = true;
2949 bp = mSettings.mPermissionTrees.get(p.info.name);
2950 }
2951 if (bp != null && bp.perm == p) {
2952 if (bp.type != BasePermission.TYPE_BUILTIN) {
2953 if (tree) {
2954 mSettings.mPermissionTrees.remove(p.info.name);
2955 } else {
2956 mSettings.mPermissions.remove(p.info.name);
2957 }
2958 } else {
2959 bp.perm = null;
2960 }
2961 if (chatty) {
2962 if (r == null) {
2963 r = new StringBuilder(256);
2964 } else {
2965 r.append(' ');
2966 }
2967 r.append(p.info.name);
2968 }
2969 }
2970 }
2971 if (r != null) {
2972 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2973 }
2974
2975 N = pkg.instrumentation.size();
2976 r = null;
2977 for (i=0; i<N; i++) {
2978 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2979 mInstrumentation.remove(a.component);
2980 if (chatty) {
2981 if (r == null) {
2982 r = new StringBuilder(256);
2983 } else {
2984 r.append(' ');
2985 }
2986 r.append(a.info.name);
2987 }
2988 }
2989 if (r != null) {
2990 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2991 }
2992 }
2993 }
2994
2995 private static final boolean isPackageFilename(String name) {
2996 return name != null && name.endsWith(".apk");
2997 }
2998
2999 private void updatePermissionsLP() {
3000 // Make sure there are no dangling permission trees.
3001 Iterator<BasePermission> it = mSettings.mPermissionTrees
3002 .values().iterator();
3003 while (it.hasNext()) {
3004 BasePermission bp = it.next();
3005 if (bp.perm == null) {
3006 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3007 + " from package " + bp.sourcePackage);
3008 it.remove();
3009 }
3010 }
3011
3012 // Make sure all dynamic permissions have been assigned to a package,
3013 // and make sure there are no dangling permissions.
3014 it = mSettings.mPermissions.values().iterator();
3015 while (it.hasNext()) {
3016 BasePermission bp = it.next();
3017 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3018 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3019 + bp.name + " pkg=" + bp.sourcePackage
3020 + " info=" + bp.pendingInfo);
3021 if (bp.perm == null && bp.pendingInfo != null) {
3022 BasePermission tree = findPermissionTreeLP(bp.name);
3023 if (tree != null) {
3024 bp.perm = new PackageParser.Permission(tree.perm.owner,
3025 new PermissionInfo(bp.pendingInfo));
3026 bp.perm.info.packageName = tree.perm.info.packageName;
3027 bp.perm.info.name = bp.name;
3028 bp.uid = tree.uid;
3029 }
3030 }
3031 }
3032 if (bp.perm == null) {
3033 Log.w(TAG, "Removing dangling permission: " + bp.name
3034 + " from package " + bp.sourcePackage);
3035 it.remove();
3036 }
3037 }
3038
3039 // Now update the permissions for all packages, in particular
3040 // replace the granted permissions of the system packages.
3041 for (PackageParser.Package pkg : mPackages.values()) {
3042 grantPermissionsLP(pkg, false);
3043 }
3044 }
3045
3046 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3047 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3048 if (ps == null) {
3049 return;
3050 }
3051 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3052 boolean addedPermission = false;
3053
3054 if (replace) {
3055 ps.permissionsFixed = false;
3056 if (gp == ps) {
3057 gp.grantedPermissions.clear();
3058 gp.gids = mGlobalGids;
3059 }
3060 }
3061
3062 if (gp.gids == null) {
3063 gp.gids = mGlobalGids;
3064 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07003065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 final int N = pkg.requestedPermissions.size();
3067 for (int i=0; i<N; i++) {
3068 String name = pkg.requestedPermissions.get(i);
3069 BasePermission bp = mSettings.mPermissions.get(name);
3070 PackageParser.Permission p = bp != null ? bp.perm : null;
3071 if (false) {
3072 if (gp != ps) {
3073 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3074 + ": " + p);
3075 }
3076 }
3077 if (p != null) {
3078 final String perm = p.info.name;
3079 boolean allowed;
3080 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3081 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3082 allowed = true;
3083 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3084 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003085 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003087 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 == PackageManager.SIGNATURE_MATCH);
3089 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3090 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3091 // For updated system applications, the signatureOrSystem permission
3092 // is granted only if it had been defined by the original application.
3093 if ((pkg.applicationInfo.flags
3094 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3095 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3096 if(sysPs.grantedPermissions.contains(perm)) {
3097 allowed = true;
3098 } else {
3099 allowed = false;
3100 }
3101 } else {
3102 allowed = true;
3103 }
3104 }
3105 }
3106 } else {
3107 allowed = false;
3108 }
3109 if (false) {
3110 if (gp != ps) {
3111 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3112 }
3113 }
3114 if (allowed) {
3115 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3116 && ps.permissionsFixed) {
3117 // If this is an existing, non-system package, then
3118 // we can't add any new permissions to it.
3119 if (!gp.loadedPermissions.contains(perm)) {
3120 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003121 // Except... if this is a permission that was added
3122 // to the platform (note: need to only do this when
3123 // updating the platform).
3124 final int NP = PackageParser.NEW_PERMISSIONS.length;
3125 for (int ip=0; ip<NP; ip++) {
3126 final PackageParser.NewPermissionInfo npi
3127 = PackageParser.NEW_PERMISSIONS[ip];
3128 if (npi.name.equals(perm)
3129 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3130 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003131 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003132 + pkg.packageName);
3133 break;
3134 }
3135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 }
3137 }
3138 if (allowed) {
3139 if (!gp.grantedPermissions.contains(perm)) {
3140 addedPermission = true;
3141 gp.grantedPermissions.add(perm);
3142 gp.gids = appendInts(gp.gids, bp.gids);
3143 }
3144 } else {
3145 Log.w(TAG, "Not granting permission " + perm
3146 + " to package " + pkg.packageName
3147 + " because it was previously installed without");
3148 }
3149 } else {
3150 Log.w(TAG, "Not granting permission " + perm
3151 + " to package " + pkg.packageName
3152 + " (protectionLevel=" + p.info.protectionLevel
3153 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3154 + ")");
3155 }
3156 } else {
3157 Log.w(TAG, "Unknown permission " + name
3158 + " in package " + pkg.packageName);
3159 }
3160 }
3161
3162 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003163 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3164 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 // This is the first that we have heard about this package, so the
3166 // permissions we have now selected are fixed until explicitly
3167 // changed.
3168 ps.permissionsFixed = true;
3169 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3170 }
3171 }
3172
3173 private final class ActivityIntentResolver
3174 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003175 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003177 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 }
3179
Mihai Preda074edef2009-05-18 17:13:31 +02003180 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003182 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3184 }
3185
Mihai Predaeae850c2009-05-13 10:13:48 +02003186 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3187 ArrayList<PackageParser.Activity> packageActivities) {
3188 if (packageActivities == null) {
3189 return null;
3190 }
3191 mFlags = flags;
3192 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3193 int N = packageActivities.size();
3194 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3195 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003196
3197 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003198 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003199 intentFilters = packageActivities.get(i).intents;
3200 if (intentFilters != null && intentFilters.size() > 0) {
3201 listCut.add(intentFilters);
3202 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003203 }
3204 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3205 }
3206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 public final void addActivity(PackageParser.Activity a, String type) {
3208 mActivities.put(a.component, a);
3209 if (SHOW_INFO || Config.LOGV) Log.v(
3210 TAG, " " + type + " " +
3211 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3212 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3213 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003214 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3216 if (SHOW_INFO || Config.LOGV) {
3217 Log.v(TAG, " IntentFilter:");
3218 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3219 }
3220 if (!intent.debugCheck()) {
3221 Log.w(TAG, "==> For Activity " + a.info.name);
3222 }
3223 addFilter(intent);
3224 }
3225 }
3226
3227 public final void removeActivity(PackageParser.Activity a, String type) {
3228 mActivities.remove(a.component);
3229 if (SHOW_INFO || Config.LOGV) Log.v(
3230 TAG, " " + type + " " +
3231 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3232 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3233 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003234 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3236 if (SHOW_INFO || Config.LOGV) {
3237 Log.v(TAG, " IntentFilter:");
3238 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3239 }
3240 removeFilter(intent);
3241 }
3242 }
3243
3244 @Override
3245 protected boolean allowFilterResult(
3246 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3247 ActivityInfo filterAi = filter.activity.info;
3248 for (int i=dest.size()-1; i>=0; i--) {
3249 ActivityInfo destAi = dest.get(i).activityInfo;
3250 if (destAi.name == filterAi.name
3251 && destAi.packageName == filterAi.packageName) {
3252 return false;
3253 }
3254 }
3255 return true;
3256 }
3257
3258 @Override
3259 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3260 int match) {
3261 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3262 return null;
3263 }
3264 final PackageParser.Activity activity = info.activity;
3265 if (mSafeMode && (activity.info.applicationInfo.flags
3266 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3267 return null;
3268 }
3269 final ResolveInfo res = new ResolveInfo();
3270 res.activityInfo = PackageParser.generateActivityInfo(activity,
3271 mFlags);
3272 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3273 res.filter = info;
3274 }
3275 res.priority = info.getPriority();
3276 res.preferredOrder = activity.owner.mPreferredOrder;
3277 //System.out.println("Result: " + res.activityInfo.className +
3278 // " = " + res.priority);
3279 res.match = match;
3280 res.isDefault = info.hasDefault;
3281 res.labelRes = info.labelRes;
3282 res.nonLocalizedLabel = info.nonLocalizedLabel;
3283 res.icon = info.icon;
3284 return res;
3285 }
3286
3287 @Override
3288 protected void sortResults(List<ResolveInfo> results) {
3289 Collections.sort(results, mResolvePrioritySorter);
3290 }
3291
3292 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003293 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003295 out.print(prefix); out.print(
3296 Integer.toHexString(System.identityHashCode(filter.activity)));
3297 out.print(' ');
3298 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 }
3300
3301// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3302// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3303// final List<ResolveInfo> retList = Lists.newArrayList();
3304// while (i.hasNext()) {
3305// final ResolveInfo resolveInfo = i.next();
3306// if (isEnabledLP(resolveInfo.activityInfo)) {
3307// retList.add(resolveInfo);
3308// }
3309// }
3310// return retList;
3311// }
3312
3313 // Keys are String (activity class name), values are Activity.
3314 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3315 = new HashMap<ComponentName, PackageParser.Activity>();
3316 private int mFlags;
3317 }
3318
3319 private final class ServiceIntentResolver
3320 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003321 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003323 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325
Mihai Preda074edef2009-05-18 17:13:31 +02003326 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003328 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3330 }
3331
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003332 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3333 ArrayList<PackageParser.Service> packageServices) {
3334 if (packageServices == null) {
3335 return null;
3336 }
3337 mFlags = flags;
3338 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3339 int N = packageServices.size();
3340 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3341 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3342
3343 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3344 for (int i = 0; i < N; ++i) {
3345 intentFilters = packageServices.get(i).intents;
3346 if (intentFilters != null && intentFilters.size() > 0) {
3347 listCut.add(intentFilters);
3348 }
3349 }
3350 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3351 }
3352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 public final void addService(PackageParser.Service s) {
3354 mServices.put(s.component, s);
3355 if (SHOW_INFO || Config.LOGV) Log.v(
3356 TAG, " " + (s.info.nonLocalizedLabel != null
3357 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3358 if (SHOW_INFO || Config.LOGV) Log.v(
3359 TAG, " Class=" + s.info.name);
3360 int NI = s.intents.size();
3361 int j;
3362 for (j=0; j<NI; j++) {
3363 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3364 if (SHOW_INFO || Config.LOGV) {
3365 Log.v(TAG, " IntentFilter:");
3366 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3367 }
3368 if (!intent.debugCheck()) {
3369 Log.w(TAG, "==> For Service " + s.info.name);
3370 }
3371 addFilter(intent);
3372 }
3373 }
3374
3375 public final void removeService(PackageParser.Service s) {
3376 mServices.remove(s.component);
3377 if (SHOW_INFO || Config.LOGV) Log.v(
3378 TAG, " " + (s.info.nonLocalizedLabel != null
3379 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3380 if (SHOW_INFO || Config.LOGV) Log.v(
3381 TAG, " Class=" + s.info.name);
3382 int NI = s.intents.size();
3383 int j;
3384 for (j=0; j<NI; j++) {
3385 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3386 if (SHOW_INFO || Config.LOGV) {
3387 Log.v(TAG, " IntentFilter:");
3388 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3389 }
3390 removeFilter(intent);
3391 }
3392 }
3393
3394 @Override
3395 protected boolean allowFilterResult(
3396 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3397 ServiceInfo filterSi = filter.service.info;
3398 for (int i=dest.size()-1; i>=0; i--) {
3399 ServiceInfo destAi = dest.get(i).serviceInfo;
3400 if (destAi.name == filterSi.name
3401 && destAi.packageName == filterSi.packageName) {
3402 return false;
3403 }
3404 }
3405 return true;
3406 }
3407
3408 @Override
3409 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3410 int match) {
3411 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3412 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3413 return null;
3414 }
3415 final PackageParser.Service service = info.service;
3416 if (mSafeMode && (service.info.applicationInfo.flags
3417 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3418 return null;
3419 }
3420 final ResolveInfo res = new ResolveInfo();
3421 res.serviceInfo = PackageParser.generateServiceInfo(service,
3422 mFlags);
3423 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3424 res.filter = filter;
3425 }
3426 res.priority = info.getPriority();
3427 res.preferredOrder = service.owner.mPreferredOrder;
3428 //System.out.println("Result: " + res.activityInfo.className +
3429 // " = " + res.priority);
3430 res.match = match;
3431 res.isDefault = info.hasDefault;
3432 res.labelRes = info.labelRes;
3433 res.nonLocalizedLabel = info.nonLocalizedLabel;
3434 res.icon = info.icon;
3435 return res;
3436 }
3437
3438 @Override
3439 protected void sortResults(List<ResolveInfo> results) {
3440 Collections.sort(results, mResolvePrioritySorter);
3441 }
3442
3443 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003444 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003446 out.print(prefix); out.print(
3447 Integer.toHexString(System.identityHashCode(filter.service)));
3448 out.print(' ');
3449 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 }
3451
3452// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3453// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3454// final List<ResolveInfo> retList = Lists.newArrayList();
3455// while (i.hasNext()) {
3456// final ResolveInfo resolveInfo = (ResolveInfo) i;
3457// if (isEnabledLP(resolveInfo.serviceInfo)) {
3458// retList.add(resolveInfo);
3459// }
3460// }
3461// return retList;
3462// }
3463
3464 // Keys are String (activity class name), values are Activity.
3465 private final HashMap<ComponentName, PackageParser.Service> mServices
3466 = new HashMap<ComponentName, PackageParser.Service>();
3467 private int mFlags;
3468 };
3469
3470 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3471 new Comparator<ResolveInfo>() {
3472 public int compare(ResolveInfo r1, ResolveInfo r2) {
3473 int v1 = r1.priority;
3474 int v2 = r2.priority;
3475 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3476 if (v1 != v2) {
3477 return (v1 > v2) ? -1 : 1;
3478 }
3479 v1 = r1.preferredOrder;
3480 v2 = r2.preferredOrder;
3481 if (v1 != v2) {
3482 return (v1 > v2) ? -1 : 1;
3483 }
3484 if (r1.isDefault != r2.isDefault) {
3485 return r1.isDefault ? -1 : 1;
3486 }
3487 v1 = r1.match;
3488 v2 = r2.match;
3489 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3490 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3491 }
3492 };
3493
3494 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3495 new Comparator<ProviderInfo>() {
3496 public int compare(ProviderInfo p1, ProviderInfo p2) {
3497 final int v1 = p1.initOrder;
3498 final int v2 = p2.initOrder;
3499 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3500 }
3501 };
3502
3503 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3504 IActivityManager am = ActivityManagerNative.getDefault();
3505 if (am != null) {
3506 try {
3507 final Intent intent = new Intent(action,
3508 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3509 if (extras != null) {
3510 intent.putExtras(extras);
3511 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003512 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 am.broadcastIntent(
3514 null, intent,
3515 null, null, 0, null, null, null, false, false);
3516 } catch (RemoteException ex) {
3517 }
3518 }
3519 }
3520
3521 private final class AppDirObserver extends FileObserver {
3522 public AppDirObserver(String path, int mask, boolean isrom) {
3523 super(path, mask);
3524 mRootDir = path;
3525 mIsRom = isrom;
3526 }
3527
3528 public void onEvent(int event, String path) {
3529 String removedPackage = null;
3530 int removedUid = -1;
3531 String addedPackage = null;
3532 int addedUid = -1;
3533
3534 synchronized (mInstallLock) {
3535 String fullPathStr = null;
3536 File fullPath = null;
3537 if (path != null) {
3538 fullPath = new File(mRootDir, path);
3539 fullPathStr = fullPath.getPath();
3540 }
3541
3542 if (Config.LOGV) Log.v(
3543 TAG, "File " + fullPathStr + " changed: "
3544 + Integer.toHexString(event));
3545
3546 if (!isPackageFilename(path)) {
3547 if (Config.LOGV) Log.v(
3548 TAG, "Ignoring change of non-package file: " + fullPathStr);
3549 return;
3550 }
3551
3552 if ((event&REMOVE_EVENTS) != 0) {
3553 synchronized (mInstallLock) {
3554 PackageParser.Package p = mAppDirs.get(fullPathStr);
3555 if (p != null) {
3556 removePackageLI(p, true);
3557 removedPackage = p.applicationInfo.packageName;
3558 removedUid = p.applicationInfo.uid;
3559 }
3560 }
3561 }
3562
3563 if ((event&ADD_EVENTS) != 0) {
3564 PackageParser.Package p = mAppDirs.get(fullPathStr);
3565 if (p == null) {
3566 p = scanPackageLI(fullPath, fullPath, fullPath,
3567 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3568 PackageParser.PARSE_CHATTY |
3569 PackageParser.PARSE_MUST_BE_APK,
3570 SCAN_MONITOR);
3571 if (p != null) {
3572 synchronized (mPackages) {
3573 grantPermissionsLP(p, false);
3574 }
3575 addedPackage = p.applicationInfo.packageName;
3576 addedUid = p.applicationInfo.uid;
3577 }
3578 }
3579 }
3580
3581 synchronized (mPackages) {
3582 mSettings.writeLP();
3583 }
3584 }
3585
3586 if (removedPackage != null) {
3587 Bundle extras = new Bundle(1);
3588 extras.putInt(Intent.EXTRA_UID, removedUid);
3589 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3590 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3591 }
3592 if (addedPackage != null) {
3593 Bundle extras = new Bundle(1);
3594 extras.putInt(Intent.EXTRA_UID, addedUid);
3595 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3596 }
3597 }
3598
3599 private final String mRootDir;
3600 private final boolean mIsRom;
3601 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 /* 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) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003606 installPackage(packageURI, observer, flags, null);
3607 }
3608
3609 /* Called when a downloaded package installation has been confirmed by the user */
3610 public void installPackage(
3611 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3612 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 mContext.enforceCallingOrSelfPermission(
3614 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 // Queue up an async operation since the package installation may take a little while.
3617 mHandler.post(new Runnable() {
3618 public void run() {
3619 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003620 // Result object to be returned
3621 PackageInstalledInfo res = new PackageInstalledInfo();
3622 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3623 res.uid = -1;
3624 res.pkg = null;
3625 res.removedInfo = new PackageRemovedInfo();
3626 // Make a temporary copy of file from given packageURI
3627 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3628 if (tmpPackageFile != null) {
3629 synchronized (mInstallLock) {
3630 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 }
3633 if (observer != null) {
3634 try {
3635 observer.packageInstalled(res.name, res.returnCode);
3636 } catch (RemoteException e) {
3637 Log.i(TAG, "Observer no longer exists.");
3638 }
3639 }
3640 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3641 // call appears in the synchronized block above.
3642 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3643 res.removedInfo.sendBroadcast(false, true);
3644 Bundle extras = new Bundle(1);
3645 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003646 final boolean update = res.removedInfo.removedPackage != null;
3647 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3649 }
3650 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3651 res.pkg.applicationInfo.packageName,
3652 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003653 if (update) {
3654 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3655 res.pkg.applicationInfo.packageName,
3656 extras);
3657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 }
3659 Runtime.getRuntime().gc();
3660 }
3661 });
3662 }
3663
3664 class PackageInstalledInfo {
3665 String name;
3666 int uid;
3667 PackageParser.Package pkg;
3668 int returnCode;
3669 PackageRemovedInfo removedInfo;
3670 }
3671
3672 /*
3673 * Install a non-existing package.
3674 */
3675 private void installNewPackageLI(String pkgName,
3676 File tmpPackageFile,
3677 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003678 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003679 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 // Remember this for later, in case we need to rollback this install
3681 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3682 res.name = pkgName;
3683 synchronized(mPackages) {
3684 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3685 // Don't allow installation over an existing package with the same name.
3686 Log.w(TAG, "Attempt to re-install " + pkgName
3687 + " without first uninstalling.");
3688 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3689 return;
3690 }
3691 }
3692 if (destPackageFile.exists()) {
3693 // It's safe to do this because we know (from the above check) that the file
3694 // isn't currently used for an installed package.
3695 destPackageFile.delete();
3696 }
3697 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3698 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3699 destResourceFile, pkg, 0,
3700 SCAN_MONITOR | SCAN_FORCE_DEX
3701 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003702 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3703 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 if (newPackage == null) {
3705 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3706 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3707 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3708 }
3709 } else {
3710 updateSettingsLI(pkgName, tmpPackageFile,
3711 destFilePath, destPackageFile,
3712 destResourceFile, pkg,
3713 newPackage,
3714 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003715 forwardLocked,
3716 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 res);
3718 // delete the partially installed application. the data directory will have to be
3719 // restored if it was already existing
3720 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3721 // remove package from internal structures. Note that we want deletePackageX to
3722 // delete the package data and cache directories that it created in
3723 // scanPackageLocked, unless those directories existed before we even tried to
3724 // install.
3725 deletePackageLI(
3726 pkgName, true,
3727 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3728 res.removedInfo);
3729 }
3730 }
3731 }
3732
3733 private void replacePackageLI(String pkgName,
3734 File tmpPackageFile,
3735 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003736 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003737 String installerPackageName, PackageInstalledInfo res) {
3738
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003739 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 // First find the old package info and check signatures
3741 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003742 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003743 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3744 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3746 return;
3747 }
3748 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003749 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003751 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003753 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003754 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003756 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003757 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003758 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 }
3760 }
3761
3762 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3763 File tmpPackageFile,
3764 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003765 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003766 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 PackageParser.Package newPackage = null;
3768 String pkgName = deletedPackage.packageName;
3769 boolean deletedPkg = true;
3770 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003771
3772 String oldInstallerPackageName = null;
3773 synchronized (mPackages) {
3774 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3775 }
3776
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003777 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 // First delete the existing package while retaining the data directory
3779 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3780 res.removedInfo)) {
3781 // If the existing package was'nt successfully deleted
3782 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3783 deletedPkg = false;
3784 } else {
3785 // Successfully deleted the old package. Now proceed with re-installation
3786 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3787 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3788 destResourceFile, pkg, parseFlags,
3789 SCAN_MONITOR | SCAN_FORCE_DEX
3790 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003791 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3792 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 if (newPackage == null) {
3794 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3795 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3796 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3797 }
3798 } else {
3799 updateSettingsLI(pkgName, tmpPackageFile,
3800 destFilePath, destPackageFile,
3801 destResourceFile, pkg,
3802 newPackage,
3803 true,
3804 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003805 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003806 res);
3807 updatedSettings = true;
3808 }
3809 }
3810
3811 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3812 // If we deleted an exisiting package, the old source and resource files that we
3813 // were keeping around in case we needed them (see below) can now be deleted
3814 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3815 final ApplicationInfo installedPackageAppInfo =
3816 newPackage.applicationInfo;
3817 if (!deletedPackageAppInfo.sourceDir
3818 .equals(installedPackageAppInfo.sourceDir)) {
3819 new File(deletedPackageAppInfo.sourceDir).delete();
3820 }
3821 if (!deletedPackageAppInfo.publicSourceDir
3822 .equals(installedPackageAppInfo.publicSourceDir)) {
3823 new File(deletedPackageAppInfo.publicSourceDir).delete();
3824 }
3825 //update signature on the new package setting
3826 //this should always succeed, since we checked the
3827 //signature earlier.
3828 synchronized(mPackages) {
3829 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3830 parseFlags, true);
3831 }
3832 } else {
3833 // remove package from internal structures. Note that we want deletePackageX to
3834 // delete the package data and cache directories that it created in
3835 // scanPackageLocked, unless those directories existed before we even tried to
3836 // install.
3837 if(updatedSettings) {
3838 deletePackageLI(
3839 pkgName, true,
3840 PackageManager.DONT_DELETE_DATA,
3841 res.removedInfo);
3842 }
3843 // Since we failed to install the new package we need to restore the old
3844 // package that we deleted.
3845 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003846 File restoreFile = new File(deletedPackage.mPath);
3847 if (restoreFile == null) {
3848 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
3849 return;
3850 }
3851 File restoreTmpFile = createTempPackageFile();
3852 if (restoreTmpFile == null) {
3853 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
3854 return;
3855 }
3856 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
3857 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
3858 return;
3859 }
3860 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
3861 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003863 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003865 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003866 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
3867 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3868 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
3869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 }
3871 }
3872 }
3873
3874 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3875 File tmpPackageFile,
3876 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003877 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003878 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 PackageParser.Package newPackage = null;
3880 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003881 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 PackageParser.PARSE_IS_SYSTEM;
3883 String packageName = deletedPackage.packageName;
3884 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3885 if (packageName == null) {
3886 Log.w(TAG, "Attempt to delete null packageName.");
3887 return;
3888 }
3889 PackageParser.Package oldPkg;
3890 PackageSetting oldPkgSetting;
3891 synchronized (mPackages) {
3892 oldPkg = mPackages.get(packageName);
3893 oldPkgSetting = mSettings.mPackages.get(packageName);
3894 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3895 (oldPkgSetting == null)) {
3896 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3897 return;
3898 }
3899 }
3900 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3901 res.removedInfo.removedPackage = packageName;
3902 // Remove existing system package
3903 removePackageLI(oldPkg, true);
3904 synchronized (mPackages) {
3905 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3906 }
3907
3908 // Successfully disabled the old package. Now proceed with re-installation
3909 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3910 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3911 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3912 destResourceFile, pkg, parseFlags,
3913 SCAN_MONITOR | SCAN_FORCE_DEX
3914 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003915 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3916 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 if (newPackage == null) {
3918 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3919 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3920 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3921 }
3922 } else {
3923 updateSettingsLI(packageName, tmpPackageFile,
3924 destFilePath, destPackageFile,
3925 destResourceFile, pkg,
3926 newPackage,
3927 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003928 forwardLocked,
3929 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 res);
3931 updatedSettings = true;
3932 }
3933
3934 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3935 //update signature on the new package setting
3936 //this should always succeed, since we checked the
3937 //signature earlier.
3938 synchronized(mPackages) {
3939 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3940 parseFlags, true);
3941 }
3942 } else {
3943 // Re installation failed. Restore old information
3944 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07003945 if (newPackage != null) {
3946 removePackageLI(newPackage, true);
3947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 // Add back the old system package
3949 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3950 oldPkgSetting.resourcePath,
3951 oldPkg, parseFlags,
3952 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003953 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 // Restore the old system information in Settings
3955 synchronized(mPackages) {
3956 if(updatedSettings) {
3957 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02003958 mSettings.setInstallerPackageName(packageName,
3959 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
3961 mSettings.writeLP();
3962 }
3963 }
3964 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07003965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3967 String destFilePath, File destPackageFile,
3968 File destResourceFile,
3969 PackageParser.Package pkg,
3970 PackageParser.Package newPackage,
3971 boolean replacingExistingPackage,
3972 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003973 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 synchronized (mPackages) {
3975 //write settings. the installStatus will be incomplete at this stage.
3976 //note that the new package setting would have already been
3977 //added to mPackages. It hasn't been persisted yet.
3978 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3979 mSettings.writeLP();
3980 }
3981
3982 int retCode = 0;
3983 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3984 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3985 destPackageFile.toString());
3986 if (retCode != 0) {
3987 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3988 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3989 return;
3990 }
3991 }
3992 // XXX There are probably some big issues here: upon doing
3993 // the rename, we have reached the point of no return (the
3994 // original .apk is gone!), so we can't fail. Yet... we can.
3995 if (!tmpPackageFile.renameTo(destPackageFile)) {
3996 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3997 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3998 } else {
3999 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4000 destResourceFile,
4001 forwardLocked);
4002 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4003 return;
4004 } else {
4005 Log.d(TAG, "New package installed in " + destPackageFile);
4006 }
4007 }
4008 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4009 if (mInstaller != null) {
4010 mInstaller.rmdex(tmpPackageFile.getPath());
4011 }
4012 }
4013
4014 synchronized (mPackages) {
4015 grantPermissionsLP(newPackage, true);
4016 res.name = pkgName;
4017 res.uid = newPackage.applicationInfo.uid;
4018 res.pkg = newPackage;
4019 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004020 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4022 //to update install status
4023 mSettings.writeLP();
4024 }
4025 }
4026
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004027 private File getFwdLockedResource(String pkgName) {
4028 final String publicZipFileName = pkgName + ".zip";
4029 return new File(mAppInstallDir, publicZipFileName);
4030 }
4031
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004032 private File copyTempInstallFile(Uri pPackageURI,
4033 PackageInstalledInfo res) {
4034 File tmpPackageFile = createTempPackageFile();
4035 int retCode = PackageManager.INSTALL_SUCCEEDED;
4036 if (tmpPackageFile == null) {
4037 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4038 return null;
4039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004041 if (pPackageURI.getScheme().equals("file")) {
4042 final File srcPackageFile = new File(pPackageURI.getPath());
4043 // We copy the source package file to a temp file and then rename it to the
4044 // destination file in order to eliminate a window where the package directory
4045 // scanner notices the new package file but it's not completely copied yet.
4046 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4047 Log.e(TAG, "Couldn't copy package file to temp file.");
4048 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004050 } else if (pPackageURI.getScheme().equals("content")) {
4051 ParcelFileDescriptor fd = null;
4052 try {
4053 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4054 } catch (FileNotFoundException e) {
4055 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4056 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4057 }
4058 if (fd == null) {
4059 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4060 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4061 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004062 if (Config.LOGV) {
4063 Log.v(TAG, "Opened file descriptor from download service.");
4064 }
4065 ParcelFileDescriptor.AutoCloseInputStream
4066 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4067 // We copy the source package file to a temp file and then rename it to the
4068 // destination file in order to eliminate a window where the package directory
4069 // scanner notices the new package file but it's not completely copied yet.
4070 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4071 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004072 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004074 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004075 } else {
4076 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4077 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4078 }
4079
4080 res.returnCode = retCode;
4081 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4082 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4083 tmpPackageFile.delete();
4084 }
4085 return null;
4086 }
4087 return tmpPackageFile;
4088 }
4089
4090 private void installPackageLI(Uri pPackageURI,
4091 int pFlags, boolean newInstall, String installerPackageName,
4092 File tmpPackageFile, PackageInstalledInfo res) {
4093 String pkgName = null;
4094 boolean forwardLocked = false;
4095 boolean replacingExistingPackage = false;
4096 // Result object to be returned
4097 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4098
4099 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 pkgName = PackageParser.parsePackageName(
4101 tmpPackageFile.getAbsolutePath(), 0);
4102 if (pkgName == null) {
4103 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4104 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4105 break main_flow;
4106 }
4107 res.name = pkgName;
4108 //initialize some variables before installing pkg
4109 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004110 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111 ? mDrmAppPrivateInstallDir
4112 : mAppInstallDir;
4113 final File destPackageFile = new File(destDir, pkgFileName);
4114 final String destFilePath = destPackageFile.getAbsolutePath();
4115 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004116 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004117 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 forwardLocked = true;
4119 } else {
4120 destResourceFile = destPackageFile;
4121 }
4122 // Retrieve PackageSettings and parse package
4123 int parseFlags = PackageParser.PARSE_CHATTY;
4124 parseFlags |= mDefParseFlags;
4125 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4126 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07004127 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4129 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4130 if (pkg == null) {
4131 res.returnCode = pp.getParseError();
4132 break main_flow;
4133 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004134 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4135 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4136 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4137 break main_flow;
4138 }
4139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4141 res.returnCode = pp.getParseError();
4142 break main_flow;
4143 }
4144
4145 synchronized (mPackages) {
4146 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004147 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 && mPackages.containsKey(pkgName)) {
4149 replacingExistingPackage = true;
4150 }
4151 }
4152
4153 if(replacingExistingPackage) {
4154 replacePackageLI(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 } else {
4160 installNewPackageLI(pkgName,
4161 tmpPackageFile,
4162 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004163 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 res);
4165 }
4166 } finally {
4167 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4168 tmpPackageFile.delete();
4169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 }
4171 }
4172
4173 private int setPermissionsLI(String pkgName,
4174 PackageParser.Package newPackage,
4175 String destFilePath,
4176 File destResourceFile,
4177 boolean forwardLocked) {
4178 int retCode;
4179 if (forwardLocked) {
4180 try {
4181 extractPublicFiles(newPackage, destResourceFile);
4182 } catch (IOException e) {
4183 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4184 " forward-locked app.");
4185 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4186 } finally {
4187 //TODO clean up the extracted public files
4188 }
4189 if (mInstaller != null) {
4190 retCode = mInstaller.setForwardLockPerm(pkgName,
4191 newPackage.applicationInfo.uid);
4192 } else {
4193 final int filePermissions =
4194 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4195 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4196 newPackage.applicationInfo.uid);
4197 }
4198 } else {
4199 final int filePermissions =
4200 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4201 |FileUtils.S_IROTH;
4202 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4203 }
4204 if (retCode != 0) {
4205 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4206 + ". The return code was: " + retCode);
4207 }
4208 return PackageManager.INSTALL_SUCCEEDED;
4209 }
4210
4211 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4212 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4213 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4214 }
4215
4216 private void extractPublicFiles(PackageParser.Package newPackage,
4217 File publicZipFile) throws IOException {
4218 final ZipOutputStream publicZipOutStream =
4219 new ZipOutputStream(new FileOutputStream(publicZipFile));
4220 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4221
4222 // Copy manifest, resources.arsc and res directory to public zip
4223
4224 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4225 while (privateZipEntries.hasMoreElements()) {
4226 final ZipEntry zipEntry = privateZipEntries.nextElement();
4227 final String zipEntryName = zipEntry.getName();
4228 if ("AndroidManifest.xml".equals(zipEntryName)
4229 || "resources.arsc".equals(zipEntryName)
4230 || zipEntryName.startsWith("res/")) {
4231 try {
4232 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4233 } catch (IOException e) {
4234 try {
4235 publicZipOutStream.close();
4236 throw e;
4237 } finally {
4238 publicZipFile.delete();
4239 }
4240 }
4241 }
4242 }
4243
4244 publicZipOutStream.close();
4245 FileUtils.setPermissions(
4246 publicZipFile.getAbsolutePath(),
4247 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4248 -1, -1);
4249 }
4250
4251 private static void copyZipEntry(ZipEntry zipEntry,
4252 ZipFile inZipFile,
4253 ZipOutputStream outZipStream) throws IOException {
4254 byte[] buffer = new byte[4096];
4255 int num;
4256
4257 ZipEntry newEntry;
4258 if (zipEntry.getMethod() == ZipEntry.STORED) {
4259 // Preserve the STORED method of the input entry.
4260 newEntry = new ZipEntry(zipEntry);
4261 } else {
4262 // Create a new entry so that the compressed len is recomputed.
4263 newEntry = new ZipEntry(zipEntry.getName());
4264 }
4265 outZipStream.putNextEntry(newEntry);
4266
4267 InputStream data = inZipFile.getInputStream(zipEntry);
4268 while ((num = data.read(buffer)) > 0) {
4269 outZipStream.write(buffer, 0, num);
4270 }
4271 outZipStream.flush();
4272 }
4273
4274 private void deleteTempPackageFiles() {
4275 FilenameFilter filter = new FilenameFilter() {
4276 public boolean accept(File dir, String name) {
4277 return name.startsWith("vmdl") && name.endsWith(".tmp");
4278 }
4279 };
4280 String tmpFilesList[] = mAppInstallDir.list(filter);
4281 if(tmpFilesList == null) {
4282 return;
4283 }
4284 for(int i = 0; i < tmpFilesList.length; i++) {
4285 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4286 tmpFile.delete();
4287 }
4288 }
4289
4290 private File createTempPackageFile() {
4291 File tmpPackageFile;
4292 try {
4293 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4294 } catch (IOException e) {
4295 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4296 return null;
4297 }
4298 try {
4299 FileUtils.setPermissions(
4300 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4301 -1, -1);
4302 } catch (IOException e) {
4303 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4304 return null;
4305 }
4306 return tmpPackageFile;
4307 }
4308
4309 public void deletePackage(final String packageName,
4310 final IPackageDeleteObserver observer,
4311 final int flags) {
4312 mContext.enforceCallingOrSelfPermission(
4313 android.Manifest.permission.DELETE_PACKAGES, null);
4314 // Queue up an async operation since the package deletion may take a little while.
4315 mHandler.post(new Runnable() {
4316 public void run() {
4317 mHandler.removeCallbacks(this);
4318 final boolean succeded = deletePackageX(packageName, true, true, flags);
4319 if (observer != null) {
4320 try {
4321 observer.packageDeleted(succeded);
4322 } catch (RemoteException e) {
4323 Log.i(TAG, "Observer no longer exists.");
4324 } //end catch
4325 } //end if
4326 } //end run
4327 });
4328 }
4329
4330 /**
4331 * This method is an internal method that could be get invoked either
4332 * to delete an installed package or to clean up a failed installation.
4333 * After deleting an installed package, a broadcast is sent to notify any
4334 * listeners that the package has been installed. For cleaning up a failed
4335 * installation, the broadcast is not necessary since the package's
4336 * installation wouldn't have sent the initial broadcast either
4337 * The key steps in deleting a package are
4338 * deleting the package information in internal structures like mPackages,
4339 * deleting the packages base directories through installd
4340 * updating mSettings to reflect current status
4341 * persisting settings for later use
4342 * sending a broadcast if necessary
4343 */
4344
4345 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4346 boolean deleteCodeAndResources, int flags) {
4347 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004348 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349
4350 synchronized (mInstallLock) {
4351 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4352 }
4353
4354 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004355 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4356 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4357
4358 // If the removed package was a system update, the old system packaged
4359 // was re-enabled; we need to broadcast this information
4360 if (systemUpdate) {
4361 Bundle extras = new Bundle(1);
4362 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4363 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4364
4365 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4366 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 }
4369 return res;
4370 }
4371
4372 static class PackageRemovedInfo {
4373 String removedPackage;
4374 int uid = -1;
4375 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004376 boolean isRemovedPackageSystemUpdate = false;
4377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 void sendBroadcast(boolean fullRemove, boolean replacing) {
4379 Bundle extras = new Bundle(1);
4380 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4381 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4382 if (replacing) {
4383 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4384 }
4385 if (removedPackage != null) {
4386 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4387 }
4388 if (removedUid >= 0) {
4389 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4390 }
4391 }
4392 }
4393
4394 /*
4395 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4396 * flag is not set, the data directory is removed as well.
4397 * make sure this flag is set for partially installed apps. If not its meaningless to
4398 * delete a partially installed application.
4399 */
4400 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4401 int flags) {
4402 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004403 if (outInfo != null) {
4404 outInfo.removedPackage = packageName;
4405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 removePackageLI(p, true);
4407 // Retrieve object to delete permissions for shared user later on
4408 PackageSetting deletedPs;
4409 synchronized (mPackages) {
4410 deletedPs = mSettings.mPackages.get(packageName);
4411 }
4412 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4413 if (mInstaller != null) {
4414 int retCode = mInstaller.remove(packageName);
4415 if (retCode < 0) {
4416 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4417 + packageName + ", retcode=" + retCode);
4418 // we don't consider this to be a failure of the core package deletion
4419 }
4420 } else {
4421 //for emulator
4422 PackageParser.Package pkg = mPackages.get(packageName);
4423 File dataDir = new File(pkg.applicationInfo.dataDir);
4424 dataDir.delete();
4425 }
4426 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004427 if (outInfo != null) {
4428 outInfo.removedUid = mSettings.removePackageLP(packageName);
4429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430 }
4431 }
4432 synchronized (mPackages) {
4433 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4434 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004435 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 }
4437 // Save settings now
4438 mSettings.writeLP ();
4439 }
4440 }
4441
4442 /*
4443 * Tries to delete system package.
4444 */
4445 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004446 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 ApplicationInfo applicationInfo = p.applicationInfo;
4448 //applicable for non-partially installed applications only
4449 if (applicationInfo == null) {
4450 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4451 return false;
4452 }
4453 PackageSetting ps = null;
4454 // Confirm if the system package has been updated
4455 // An updated system app can be deleted. This will also have to restore
4456 // the system pkg from system partition
4457 synchronized (mPackages) {
4458 ps = mSettings.getDisabledSystemPkg(p.packageName);
4459 }
4460 if (ps == null) {
4461 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4462 return false;
4463 } else {
4464 Log.i(TAG, "Deleting system pkg from data partition");
4465 }
4466 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004467 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004468 boolean deleteCodeAndResources = false;
4469 if (ps.versionCode < p.mVersionCode) {
4470 // Delete code and resources for downgrades
4471 deleteCodeAndResources = true;
4472 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4473 flags &= ~PackageManager.DONT_DELETE_DATA;
4474 }
4475 } else {
4476 // Preserve data by setting flag
4477 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4478 flags |= PackageManager.DONT_DELETE_DATA;
4479 }
4480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4482 if (!ret) {
4483 return false;
4484 }
4485 synchronized (mPackages) {
4486 // Reinstate the old system package
4487 mSettings.enableSystemPackageLP(p.packageName);
4488 }
4489 // Install the system package
4490 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4491 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4492 SCAN_MONITOR);
4493
4494 if (newPkg == null) {
4495 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4496 return false;
4497 }
4498 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004499 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 mSettings.writeLP();
4501 }
4502 return true;
4503 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004504
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004505 private void deletePackageResourcesLI(String packageName,
4506 String sourceDir, String publicSourceDir) {
4507 File sourceFile = new File(sourceDir);
4508 if (!sourceFile.exists()) {
4509 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4510 }
4511 // Delete application's code and resources
4512 sourceFile.delete();
4513 final File publicSourceFile = new File(publicSourceDir);
4514 if (publicSourceFile.exists()) {
4515 publicSourceFile.delete();
4516 }
4517 if (mInstaller != null) {
4518 int retCode = mInstaller.rmdex(sourceFile.toString());
4519 if (retCode < 0) {
4520 Log.w(TAG, "Couldn't remove dex file for package: "
4521 + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4522 // we don't consider this to be a failure of the core package deletion
4523 }
4524 }
4525 }
4526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4528 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4529 ApplicationInfo applicationInfo = p.applicationInfo;
4530 if (applicationInfo == null) {
4531 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4532 return false;
4533 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004534 if (outInfo != null) {
4535 outInfo.uid = applicationInfo.uid;
4536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537
4538 // Delete package data from internal structures and also remove data if flag is set
4539 removePackageDataLI(p, outInfo, flags);
4540
4541 // Delete application code and resources
4542 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004543 deletePackageResourcesLI(applicationInfo.packageName,
4544 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 }
4546 return true;
4547 }
4548
4549 /*
4550 * This method handles package deletion in general
4551 */
4552 private boolean deletePackageLI(String packageName,
4553 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4554 if (packageName == null) {
4555 Log.w(TAG, "Attempt to delete null packageName.");
4556 return false;
4557 }
4558 PackageParser.Package p;
4559 boolean dataOnly = false;
4560 synchronized (mPackages) {
4561 p = mPackages.get(packageName);
4562 if (p == null) {
4563 //this retrieves partially installed apps
4564 dataOnly = true;
4565 PackageSetting ps = mSettings.mPackages.get(packageName);
4566 if (ps == null) {
4567 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4568 return false;
4569 }
4570 p = ps.pkg;
4571 }
4572 }
4573 if (p == null) {
4574 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4575 return false;
4576 }
4577
4578 if (dataOnly) {
4579 // Delete application data first
4580 removePackageDataLI(p, outInfo, flags);
4581 return true;
4582 }
4583 // At this point the package should have ApplicationInfo associated with it
4584 if (p.applicationInfo == null) {
4585 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4586 return false;
4587 }
4588 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4589 Log.i(TAG, "Removing system package:"+p.packageName);
4590 // When an updated system application is deleted we delete the existing resources as well and
4591 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004592 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 }
4594 Log.i(TAG, "Removing non-system package:"+p.packageName);
4595 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4596 }
4597
4598 public void clearApplicationUserData(final String packageName,
4599 final IPackageDataObserver observer) {
4600 mContext.enforceCallingOrSelfPermission(
4601 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4602 // Queue up an async operation since the package deletion may take a little while.
4603 mHandler.post(new Runnable() {
4604 public void run() {
4605 mHandler.removeCallbacks(this);
4606 final boolean succeeded;
4607 synchronized (mInstallLock) {
4608 succeeded = clearApplicationUserDataLI(packageName);
4609 }
4610 if (succeeded) {
4611 // invoke DeviceStorageMonitor's update method to clear any notifications
4612 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4613 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4614 if (dsm != null) {
4615 dsm.updateMemory();
4616 }
4617 }
4618 if(observer != null) {
4619 try {
4620 observer.onRemoveCompleted(packageName, succeeded);
4621 } catch (RemoteException e) {
4622 Log.i(TAG, "Observer no longer exists.");
4623 }
4624 } //end if observer
4625 } //end run
4626 });
4627 }
4628
4629 private boolean clearApplicationUserDataLI(String packageName) {
4630 if (packageName == null) {
4631 Log.w(TAG, "Attempt to delete null packageName.");
4632 return false;
4633 }
4634 PackageParser.Package p;
4635 boolean dataOnly = false;
4636 synchronized (mPackages) {
4637 p = mPackages.get(packageName);
4638 if(p == null) {
4639 dataOnly = true;
4640 PackageSetting ps = mSettings.mPackages.get(packageName);
4641 if((ps == null) || (ps.pkg == null)) {
4642 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4643 return false;
4644 }
4645 p = ps.pkg;
4646 }
4647 }
4648 if(!dataOnly) {
4649 //need to check this only for fully installed applications
4650 if (p == null) {
4651 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4652 return false;
4653 }
4654 final ApplicationInfo applicationInfo = p.applicationInfo;
4655 if (applicationInfo == null) {
4656 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4657 return false;
4658 }
4659 }
4660 if (mInstaller != null) {
4661 int retCode = mInstaller.clearUserData(packageName);
4662 if (retCode < 0) {
4663 Log.w(TAG, "Couldn't remove cache files for package: "
4664 + packageName);
4665 return false;
4666 }
4667 }
4668 return true;
4669 }
4670
4671 public void deleteApplicationCacheFiles(final String packageName,
4672 final IPackageDataObserver observer) {
4673 mContext.enforceCallingOrSelfPermission(
4674 android.Manifest.permission.DELETE_CACHE_FILES, null);
4675 // Queue up an async operation since the package deletion may take a little while.
4676 mHandler.post(new Runnable() {
4677 public void run() {
4678 mHandler.removeCallbacks(this);
4679 final boolean succeded;
4680 synchronized (mInstallLock) {
4681 succeded = deleteApplicationCacheFilesLI(packageName);
4682 }
4683 if(observer != null) {
4684 try {
4685 observer.onRemoveCompleted(packageName, succeded);
4686 } catch (RemoteException e) {
4687 Log.i(TAG, "Observer no longer exists.");
4688 }
4689 } //end if observer
4690 } //end run
4691 });
4692 }
4693
4694 private boolean deleteApplicationCacheFilesLI(String packageName) {
4695 if (packageName == null) {
4696 Log.w(TAG, "Attempt to delete null packageName.");
4697 return false;
4698 }
4699 PackageParser.Package p;
4700 synchronized (mPackages) {
4701 p = mPackages.get(packageName);
4702 }
4703 if (p == null) {
4704 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4705 return false;
4706 }
4707 final ApplicationInfo applicationInfo = p.applicationInfo;
4708 if (applicationInfo == null) {
4709 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4710 return false;
4711 }
4712 if (mInstaller != null) {
4713 int retCode = mInstaller.deleteCacheFiles(packageName);
4714 if (retCode < 0) {
4715 Log.w(TAG, "Couldn't remove cache files for package: "
4716 + packageName);
4717 return false;
4718 }
4719 }
4720 return true;
4721 }
4722
4723 public void getPackageSizeInfo(final String packageName,
4724 final IPackageStatsObserver observer) {
4725 mContext.enforceCallingOrSelfPermission(
4726 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4727 // Queue up an async operation since the package deletion may take a little while.
4728 mHandler.post(new Runnable() {
4729 public void run() {
4730 mHandler.removeCallbacks(this);
4731 PackageStats lStats = new PackageStats(packageName);
4732 final boolean succeded;
4733 synchronized (mInstallLock) {
4734 succeded = getPackageSizeInfoLI(packageName, lStats);
4735 }
4736 if(observer != null) {
4737 try {
4738 observer.onGetStatsCompleted(lStats, succeded);
4739 } catch (RemoteException e) {
4740 Log.i(TAG, "Observer no longer exists.");
4741 }
4742 } //end if observer
4743 } //end run
4744 });
4745 }
4746
4747 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4748 if (packageName == null) {
4749 Log.w(TAG, "Attempt to get size of null packageName.");
4750 return false;
4751 }
4752 PackageParser.Package p;
4753 boolean dataOnly = false;
4754 synchronized (mPackages) {
4755 p = mPackages.get(packageName);
4756 if(p == null) {
4757 dataOnly = true;
4758 PackageSetting ps = mSettings.mPackages.get(packageName);
4759 if((ps == null) || (ps.pkg == null)) {
4760 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4761 return false;
4762 }
4763 p = ps.pkg;
4764 }
4765 }
4766 String publicSrcDir = null;
4767 if(!dataOnly) {
4768 final ApplicationInfo applicationInfo = p.applicationInfo;
4769 if (applicationInfo == null) {
4770 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4771 return false;
4772 }
4773 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4774 }
4775 if (mInstaller != null) {
4776 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4777 publicSrcDir, pStats);
4778 if (res < 0) {
4779 return false;
4780 } else {
4781 return true;
4782 }
4783 }
4784 return true;
4785 }
4786
4787
4788 public void addPackageToPreferred(String packageName) {
4789 mContext.enforceCallingOrSelfPermission(
4790 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4791
4792 synchronized (mPackages) {
4793 PackageParser.Package p = mPackages.get(packageName);
4794 if (p == null) {
4795 return;
4796 }
4797 PackageSetting ps = (PackageSetting)p.mExtras;
4798 if (ps != null) {
4799 mSettings.mPreferredPackages.remove(ps);
4800 mSettings.mPreferredPackages.add(0, ps);
4801 updatePreferredIndicesLP();
4802 mSettings.writeLP();
4803 }
4804 }
4805 }
4806
4807 public void removePackageFromPreferred(String packageName) {
4808 mContext.enforceCallingOrSelfPermission(
4809 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4810
4811 synchronized (mPackages) {
4812 PackageParser.Package p = mPackages.get(packageName);
4813 if (p == null) {
4814 return;
4815 }
4816 if (p.mPreferredOrder > 0) {
4817 PackageSetting ps = (PackageSetting)p.mExtras;
4818 if (ps != null) {
4819 mSettings.mPreferredPackages.remove(ps);
4820 p.mPreferredOrder = 0;
4821 updatePreferredIndicesLP();
4822 mSettings.writeLP();
4823 }
4824 }
4825 }
4826 }
4827
4828 private void updatePreferredIndicesLP() {
4829 final ArrayList<PackageSetting> pkgs
4830 = mSettings.mPreferredPackages;
4831 final int N = pkgs.size();
4832 for (int i=0; i<N; i++) {
4833 pkgs.get(i).pkg.mPreferredOrder = N - i;
4834 }
4835 }
4836
4837 public List<PackageInfo> getPreferredPackages(int flags) {
4838 synchronized (mPackages) {
4839 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4840 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4841 final int N = pref.size();
4842 for (int i=0; i<N; i++) {
4843 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4844 }
4845 return res;
4846 }
4847 }
4848
4849 public void addPreferredActivity(IntentFilter filter, int match,
4850 ComponentName[] set, ComponentName activity) {
4851 mContext.enforceCallingOrSelfPermission(
4852 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4853
4854 synchronized (mPackages) {
4855 Log.i(TAG, "Adding preferred activity " + activity + ":");
4856 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4857 mSettings.mPreferredActivities.addFilter(
4858 new PreferredActivity(filter, match, set, activity));
4859 mSettings.writeLP();
4860 }
4861 }
4862
Satish Sampath8dbe6122009-06-02 23:35:54 +01004863 public void replacePreferredActivity(IntentFilter filter, int match,
4864 ComponentName[] set, ComponentName activity) {
4865 mContext.enforceCallingOrSelfPermission(
4866 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4867 if (filter.countActions() != 1) {
4868 throw new IllegalArgumentException(
4869 "replacePreferredActivity expects filter to have only 1 action.");
4870 }
4871 if (filter.countCategories() != 1) {
4872 throw new IllegalArgumentException(
4873 "replacePreferredActivity expects filter to have only 1 category.");
4874 }
4875 if (filter.countDataAuthorities() != 0
4876 || filter.countDataPaths() != 0
4877 || filter.countDataSchemes() != 0
4878 || filter.countDataTypes() != 0) {
4879 throw new IllegalArgumentException(
4880 "replacePreferredActivity expects filter to have no data authorities, " +
4881 "paths, schemes or types.");
4882 }
4883 synchronized (mPackages) {
4884 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4885 String action = filter.getAction(0);
4886 String category = filter.getCategory(0);
4887 while (it.hasNext()) {
4888 PreferredActivity pa = it.next();
4889 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
4890 it.remove();
4891 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
4892 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4893 }
4894 }
4895 addPreferredActivity(filter, match, set, activity);
4896 }
4897 }
4898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 public void clearPackagePreferredActivities(String packageName) {
4900 mContext.enforceCallingOrSelfPermission(
4901 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4902
4903 synchronized (mPackages) {
4904 if (clearPackagePreferredActivitiesLP(packageName)) {
4905 mSettings.writeLP();
4906 }
4907 }
4908 }
4909
4910 boolean clearPackagePreferredActivitiesLP(String packageName) {
4911 boolean changed = false;
4912 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4913 while (it.hasNext()) {
4914 PreferredActivity pa = it.next();
4915 if (pa.mActivity.getPackageName().equals(packageName)) {
4916 it.remove();
4917 changed = true;
4918 }
4919 }
4920 return changed;
4921 }
4922
4923 public int getPreferredActivities(List<IntentFilter> outFilters,
4924 List<ComponentName> outActivities, String packageName) {
4925
4926 int num = 0;
4927 synchronized (mPackages) {
4928 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4929 while (it.hasNext()) {
4930 PreferredActivity pa = it.next();
4931 if (packageName == null
4932 || pa.mActivity.getPackageName().equals(packageName)) {
4933 if (outFilters != null) {
4934 outFilters.add(new IntentFilter(pa));
4935 }
4936 if (outActivities != null) {
4937 outActivities.add(pa.mActivity);
4938 }
4939 }
4940 }
4941 }
4942
4943 return num;
4944 }
4945
4946 public void setApplicationEnabledSetting(String appPackageName,
4947 int newState, int flags) {
4948 setEnabledSetting(appPackageName, null, newState, flags);
4949 }
4950
4951 public void setComponentEnabledSetting(ComponentName componentName,
4952 int newState, int flags) {
4953 setEnabledSetting(componentName.getPackageName(),
4954 componentName.getClassName(), newState, flags);
4955 }
4956
4957 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004958 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4960 || newState == COMPONENT_ENABLED_STATE_ENABLED
4961 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4962 throw new IllegalArgumentException("Invalid new component state: "
4963 + newState);
4964 }
4965 PackageSetting pkgSetting;
4966 final int uid = Binder.getCallingUid();
4967 final int permission = mContext.checkCallingPermission(
4968 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4969 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004970 boolean sendNow = false;
4971 boolean isApp = (className == null);
4972 String key = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 int packageUid = -1;
4974 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004975 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004977 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004979 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 }
4981 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004982 "Unknown component: " + packageName
4983 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 }
4985 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4986 throw new SecurityException(
4987 "Permission Denial: attempt to change component state from pid="
4988 + Binder.getCallingPid()
4989 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4990 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004991 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 // We're dealing with an application/package level state change
4993 pkgSetting.enabled = newState;
4994 } else {
4995 // We're dealing with a component level state change
4996 switch (newState) {
4997 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07004998 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 break;
5000 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005001 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 break;
5003 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005004 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 break;
5006 default:
5007 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005008 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005009 }
5010 }
5011 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005012 packageUid = pkgSetting.userId;
5013 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5014 sendNow = true;
5015 // Purge entry from pending broadcast list if another one exists already
5016 // since we are sending one right away.
5017 if (mPendingBroadcasts.get(key) != null) {
5018 mPendingBroadcasts.remove(key);
5019 // Can ignore empty list since its handled in the handler anyway
5020 }
5021 } else {
5022 if (mPendingBroadcasts.get(key) == null) {
5023 mPendingBroadcasts.put(key, packageName);
5024 }
5025 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5026 // Schedule a message
5027 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5028 }
5029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 long callingId = Binder.clearCallingIdentity();
5033 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005034 if (sendNow) {
5035 sendPackageChangedBroadcast(packageName,
5036 (flags&PackageManager.DONT_KILL_APP) != 0, key, packageUid);
5037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 } finally {
5039 Binder.restoreCallingIdentity(callingId);
5040 }
5041 }
5042
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005043 private void sendPackageChangedBroadcast(String packageName,
5044 boolean killFlag, String componentName, int packageUid) {
5045 Bundle extras = new Bundle(2);
5046 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentName);
5047 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5048 extras.putInt(Intent.EXTRA_UID, packageUid);
5049 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
5050 }
5051
Jacek Surazski65e13172009-04-28 15:26:38 +02005052 public String getInstallerPackageName(String packageName) {
5053 synchronized (mPackages) {
5054 PackageSetting pkg = mSettings.mPackages.get(packageName);
5055 if (pkg == null) {
5056 throw new IllegalArgumentException("Unknown package: " + packageName);
5057 }
5058 return pkg.installerPackageName;
5059 }
5060 }
5061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 public int getApplicationEnabledSetting(String appPackageName) {
5063 synchronized (mPackages) {
5064 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5065 if (pkg == null) {
5066 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5067 }
5068 return pkg.enabled;
5069 }
5070 }
5071
5072 public int getComponentEnabledSetting(ComponentName componentName) {
5073 synchronized (mPackages) {
5074 final String packageNameStr = componentName.getPackageName();
5075 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5076 if (pkg == null) {
5077 throw new IllegalArgumentException("Unknown component: " + componentName);
5078 }
5079 final String classNameStr = componentName.getClassName();
5080 return pkg.currentEnabledStateLP(classNameStr);
5081 }
5082 }
5083
5084 public void enterSafeMode() {
5085 if (!mSystemReady) {
5086 mSafeMode = true;
5087 }
5088 }
5089
5090 public void systemReady() {
5091 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005092
5093 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005094 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005095 mContext.getContentResolver(),
5096 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005097 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005098 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005099 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005101 }
5102
5103 public boolean isSafeMode() {
5104 return mSafeMode;
5105 }
5106
5107 public boolean hasSystemUidErrors() {
5108 return mHasSystemUidErrors;
5109 }
5110
5111 static String arrayToString(int[] array) {
5112 StringBuffer buf = new StringBuffer(128);
5113 buf.append('[');
5114 if (array != null) {
5115 for (int i=0; i<array.length; i++) {
5116 if (i > 0) buf.append(", ");
5117 buf.append(array[i]);
5118 }
5119 }
5120 buf.append(']');
5121 return buf.toString();
5122 }
5123
5124 @Override
5125 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5126 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5127 != PackageManager.PERMISSION_GRANTED) {
5128 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5129 + Binder.getCallingPid()
5130 + ", uid=" + Binder.getCallingUid()
5131 + " without permission "
5132 + android.Manifest.permission.DUMP);
5133 return;
5134 }
5135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136 synchronized (mPackages) {
5137 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005138 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 pw.println(" ");
5140 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005141 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 pw.println(" ");
5143 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005144 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 pw.println(" ");
5146 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005147 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005148 pw.println(" ");
5149 pw.println("Preferred Packages:");
5150 {
5151 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005152 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
5154 }
5155 pw.println(" ");
5156 pw.println("Permissions:");
5157 {
5158 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005159 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5160 pw.print(Integer.toHexString(System.identityHashCode(p)));
5161 pw.println("):");
5162 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5163 pw.print(" uid="); pw.print(p.uid);
5164 pw.print(" gids="); pw.print(arrayToString(p.gids));
5165 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 }
5167 }
5168 pw.println(" ");
5169 pw.println("Packages:");
5170 {
5171 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005172 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5173 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5174 pw.println("):");
5175 pw.print(" userId="); pw.print(ps.userId);
5176 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5177 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5178 pw.print(" pkg="); pw.println(ps.pkg);
5179 pw.print(" codePath="); pw.println(ps.codePathString);
5180 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005182 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005183 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005184 pw.print(" supportsScreens=[");
5185 boolean first = true;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005186 if ((ps.pkg.applicationInfo.flags &
5187 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005188 if (!first) pw.print(", ");
5189 first = false;
5190 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005191 }
5192 if ((ps.pkg.applicationInfo.flags &
5193 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005194 if (!first) pw.print(", ");
5195 first = false;
5196 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005197 }
5198 if ((ps.pkg.applicationInfo.flags &
5199 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005200 if (!first) pw.print(", ");
5201 first = false;
5202 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005203 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005204 if ((ps.pkg.applicationInfo.flags &
5205 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005206 if (!first) pw.print(", ");
5207 first = false;
5208 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005209 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005210 if ((ps.pkg.applicationInfo.flags &
5211 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5212 if (!first) pw.print(", ");
5213 first = false;
5214 pw.print("anyDensity");
5215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005217 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005218 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5219 pw.print(" signatures="); pw.println(ps.signatures);
5220 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5221 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5222 pw.print(" installStatus="); pw.print(ps.installStatus);
5223 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 if (ps.disabledComponents.size() > 0) {
5225 pw.println(" disabledComponents:");
5226 for (String s : ps.disabledComponents) {
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 }
5230 if (ps.enabledComponents.size() > 0) {
5231 pw.println(" enabledComponents:");
5232 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005233 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 }
5235 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005236 if (ps.grantedPermissions.size() > 0) {
5237 pw.println(" grantedPermissions:");
5238 for (String s : ps.grantedPermissions) {
5239 pw.print(" "); pw.println(s);
5240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005242 if (ps.loadedPermissions.size() > 0) {
5243 pw.println(" loadedPermissions:");
5244 for (String s : ps.loadedPermissions) {
5245 pw.print(" "); pw.println(s);
5246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 }
5248 }
5249 }
5250 pw.println(" ");
5251 pw.println("Shared Users:");
5252 {
5253 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005254 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5255 pw.print(Integer.toHexString(System.identityHashCode(su)));
5256 pw.println("):");
5257 pw.print(" userId="); pw.print(su.userId);
5258 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 pw.println(" grantedPermissions:");
5260 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005261 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005262 }
5263 pw.println(" loadedPermissions:");
5264 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005265 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 }
5267 }
5268 }
5269 pw.println(" ");
5270 pw.println("Settings parse messages:");
5271 pw.println(mSettings.mReadMessages.toString());
5272 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005273
5274 synchronized (mProviders) {
5275 pw.println(" ");
5276 pw.println("Registered ContentProviders:");
5277 for (PackageParser.Provider p : mProviders.values()) {
5278 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5279 pw.println(p.toString());
5280 }
5281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 }
5283
5284 static final class BasePermission {
5285 final static int TYPE_NORMAL = 0;
5286 final static int TYPE_BUILTIN = 1;
5287 final static int TYPE_DYNAMIC = 2;
5288
5289 final String name;
5290 final String sourcePackage;
5291 final int type;
5292 PackageParser.Permission perm;
5293 PermissionInfo pendingInfo;
5294 int uid;
5295 int[] gids;
5296
5297 BasePermission(String _name, String _sourcePackage, int _type) {
5298 name = _name;
5299 sourcePackage = _sourcePackage;
5300 type = _type;
5301 }
5302 }
5303
5304 static class PackageSignatures {
5305 private Signature[] mSignatures;
5306
5307 PackageSignatures(Signature[] sigs) {
5308 assignSignatures(sigs);
5309 }
5310
5311 PackageSignatures() {
5312 }
5313
5314 void writeXml(XmlSerializer serializer, String tagName,
5315 ArrayList<Signature> pastSignatures) throws IOException {
5316 if (mSignatures == null) {
5317 return;
5318 }
5319 serializer.startTag(null, tagName);
5320 serializer.attribute(null, "count",
5321 Integer.toString(mSignatures.length));
5322 for (int i=0; i<mSignatures.length; i++) {
5323 serializer.startTag(null, "cert");
5324 final Signature sig = mSignatures[i];
5325 final int sigHash = sig.hashCode();
5326 final int numPast = pastSignatures.size();
5327 int j;
5328 for (j=0; j<numPast; j++) {
5329 Signature pastSig = pastSignatures.get(j);
5330 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5331 serializer.attribute(null, "index", Integer.toString(j));
5332 break;
5333 }
5334 }
5335 if (j >= numPast) {
5336 pastSignatures.add(sig);
5337 serializer.attribute(null, "index", Integer.toString(numPast));
5338 serializer.attribute(null, "key", sig.toCharsString());
5339 }
5340 serializer.endTag(null, "cert");
5341 }
5342 serializer.endTag(null, tagName);
5343 }
5344
5345 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5346 throws IOException, XmlPullParserException {
5347 String countStr = parser.getAttributeValue(null, "count");
5348 if (countStr == null) {
5349 reportSettingsProblem(Log.WARN,
5350 "Error in package manager settings: <signatures> has"
5351 + " no count at " + parser.getPositionDescription());
5352 XmlUtils.skipCurrentTag(parser);
5353 }
5354 final int count = Integer.parseInt(countStr);
5355 mSignatures = new Signature[count];
5356 int pos = 0;
5357
5358 int outerDepth = parser.getDepth();
5359 int type;
5360 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5361 && (type != XmlPullParser.END_TAG
5362 || parser.getDepth() > outerDepth)) {
5363 if (type == XmlPullParser.END_TAG
5364 || type == XmlPullParser.TEXT) {
5365 continue;
5366 }
5367
5368 String tagName = parser.getName();
5369 if (tagName.equals("cert")) {
5370 if (pos < count) {
5371 String index = parser.getAttributeValue(null, "index");
5372 if (index != null) {
5373 try {
5374 int idx = Integer.parseInt(index);
5375 String key = parser.getAttributeValue(null, "key");
5376 if (key == null) {
5377 if (idx >= 0 && idx < pastSignatures.size()) {
5378 Signature sig = pastSignatures.get(idx);
5379 if (sig != null) {
5380 mSignatures[pos] = pastSignatures.get(idx);
5381 pos++;
5382 } else {
5383 reportSettingsProblem(Log.WARN,
5384 "Error in package manager settings: <cert> "
5385 + "index " + index + " is not defined at "
5386 + parser.getPositionDescription());
5387 }
5388 } else {
5389 reportSettingsProblem(Log.WARN,
5390 "Error in package manager settings: <cert> "
5391 + "index " + index + " is out of bounds at "
5392 + parser.getPositionDescription());
5393 }
5394 } else {
5395 while (pastSignatures.size() <= idx) {
5396 pastSignatures.add(null);
5397 }
5398 Signature sig = new Signature(key);
5399 pastSignatures.set(idx, sig);
5400 mSignatures[pos] = sig;
5401 pos++;
5402 }
5403 } catch (NumberFormatException e) {
5404 reportSettingsProblem(Log.WARN,
5405 "Error in package manager settings: <cert> "
5406 + "index " + index + " is not a number at "
5407 + parser.getPositionDescription());
5408 }
5409 } else {
5410 reportSettingsProblem(Log.WARN,
5411 "Error in package manager settings: <cert> has"
5412 + " no index at " + parser.getPositionDescription());
5413 }
5414 } else {
5415 reportSettingsProblem(Log.WARN,
5416 "Error in package manager settings: too "
5417 + "many <cert> tags, expected " + count
5418 + " at " + parser.getPositionDescription());
5419 }
5420 } else {
5421 reportSettingsProblem(Log.WARN,
5422 "Unknown element under <cert>: "
5423 + parser.getName());
5424 }
5425 XmlUtils.skipCurrentTag(parser);
5426 }
5427
5428 if (pos < count) {
5429 // Should never happen -- there is an error in the written
5430 // settings -- but if it does we don't want to generate
5431 // a bad array.
5432 Signature[] newSigs = new Signature[pos];
5433 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5434 mSignatures = newSigs;
5435 }
5436 }
5437
5438 /**
5439 * If any of the given 'sigs' is contained in the existing signatures,
5440 * then completely replace the current signatures with the ones in
5441 * 'sigs'. This is used for updating an existing package to a newly
5442 * installed version.
5443 */
5444 boolean updateSignatures(Signature[] sigs, boolean update) {
5445 if (mSignatures == null) {
5446 if (update) {
5447 assignSignatures(sigs);
5448 }
5449 return true;
5450 }
5451 if (sigs == null) {
5452 return false;
5453 }
5454
5455 for (int i=0; i<sigs.length; i++) {
5456 Signature sig = sigs[i];
5457 for (int j=0; j<mSignatures.length; j++) {
5458 if (mSignatures[j].equals(sig)) {
5459 if (update) {
5460 assignSignatures(sigs);
5461 }
5462 return true;
5463 }
5464 }
5465 }
5466 return false;
5467 }
5468
5469 /**
5470 * If any of the given 'sigs' is contained in the existing signatures,
5471 * then add in any new signatures found in 'sigs'. This is used for
5472 * including a new package into an existing shared user id.
5473 */
5474 boolean mergeSignatures(Signature[] sigs, boolean update) {
5475 if (mSignatures == null) {
5476 if (update) {
5477 assignSignatures(sigs);
5478 }
5479 return true;
5480 }
5481 if (sigs == null) {
5482 return false;
5483 }
5484
5485 Signature[] added = null;
5486 int addedCount = 0;
5487 boolean haveMatch = false;
5488 for (int i=0; i<sigs.length; i++) {
5489 Signature sig = sigs[i];
5490 boolean found = false;
5491 for (int j=0; j<mSignatures.length; j++) {
5492 if (mSignatures[j].equals(sig)) {
5493 found = true;
5494 haveMatch = true;
5495 break;
5496 }
5497 }
5498
5499 if (!found) {
5500 if (added == null) {
5501 added = new Signature[sigs.length];
5502 }
5503 added[i] = sig;
5504 addedCount++;
5505 }
5506 }
5507
5508 if (!haveMatch) {
5509 // Nothing matched -- reject the new signatures.
5510 return false;
5511 }
5512 if (added == null) {
5513 // Completely matched -- nothing else to do.
5514 return true;
5515 }
5516
5517 // Add additional signatures in.
5518 if (update) {
5519 Signature[] total = new Signature[addedCount+mSignatures.length];
5520 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5521 int j = mSignatures.length;
5522 for (int i=0; i<added.length; i++) {
5523 if (added[i] != null) {
5524 total[j] = added[i];
5525 j++;
5526 }
5527 }
5528 mSignatures = total;
5529 }
5530 return true;
5531 }
5532
5533 private void assignSignatures(Signature[] sigs) {
5534 if (sigs == null) {
5535 mSignatures = null;
5536 return;
5537 }
5538 mSignatures = new Signature[sigs.length];
5539 for (int i=0; i<sigs.length; i++) {
5540 mSignatures[i] = sigs[i];
5541 }
5542 }
5543
5544 @Override
5545 public String toString() {
5546 StringBuffer buf = new StringBuffer(128);
5547 buf.append("PackageSignatures{");
5548 buf.append(Integer.toHexString(System.identityHashCode(this)));
5549 buf.append(" [");
5550 if (mSignatures != null) {
5551 for (int i=0; i<mSignatures.length; i++) {
5552 if (i > 0) buf.append(", ");
5553 buf.append(Integer.toHexString(
5554 System.identityHashCode(mSignatures[i])));
5555 }
5556 }
5557 buf.append("]}");
5558 return buf.toString();
5559 }
5560 }
5561
5562 static class PreferredActivity extends IntentFilter {
5563 final int mMatch;
5564 final String[] mSetPackages;
5565 final String[] mSetClasses;
5566 final String[] mSetComponents;
5567 final ComponentName mActivity;
5568 final String mShortActivity;
5569 String mParseError;
5570
5571 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5572 ComponentName activity) {
5573 super(filter);
5574 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5575 mActivity = activity;
5576 mShortActivity = activity.flattenToShortString();
5577 mParseError = null;
5578 if (set != null) {
5579 final int N = set.length;
5580 String[] myPackages = new String[N];
5581 String[] myClasses = new String[N];
5582 String[] myComponents = new String[N];
5583 for (int i=0; i<N; i++) {
5584 ComponentName cn = set[i];
5585 if (cn == null) {
5586 mSetPackages = null;
5587 mSetClasses = null;
5588 mSetComponents = null;
5589 return;
5590 }
5591 myPackages[i] = cn.getPackageName().intern();
5592 myClasses[i] = cn.getClassName().intern();
5593 myComponents[i] = cn.flattenToShortString().intern();
5594 }
5595 mSetPackages = myPackages;
5596 mSetClasses = myClasses;
5597 mSetComponents = myComponents;
5598 } else {
5599 mSetPackages = null;
5600 mSetClasses = null;
5601 mSetComponents = null;
5602 }
5603 }
5604
5605 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5606 IOException {
5607 mShortActivity = parser.getAttributeValue(null, "name");
5608 mActivity = ComponentName.unflattenFromString(mShortActivity);
5609 if (mActivity == null) {
5610 mParseError = "Bad activity name " + mShortActivity;
5611 }
5612 String matchStr = parser.getAttributeValue(null, "match");
5613 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5614 String setCountStr = parser.getAttributeValue(null, "set");
5615 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5616
5617 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5618 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5619 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5620
5621 int setPos = 0;
5622
5623 int outerDepth = parser.getDepth();
5624 int type;
5625 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5626 && (type != XmlPullParser.END_TAG
5627 || parser.getDepth() > outerDepth)) {
5628 if (type == XmlPullParser.END_TAG
5629 || type == XmlPullParser.TEXT) {
5630 continue;
5631 }
5632
5633 String tagName = parser.getName();
5634 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5635 // + parser.getDepth() + " tag=" + tagName);
5636 if (tagName.equals("set")) {
5637 String name = parser.getAttributeValue(null, "name");
5638 if (name == null) {
5639 if (mParseError == null) {
5640 mParseError = "No name in set tag in preferred activity "
5641 + mShortActivity;
5642 }
5643 } else if (setPos >= setCount) {
5644 if (mParseError == null) {
5645 mParseError = "Too many set tags in preferred activity "
5646 + mShortActivity;
5647 }
5648 } else {
5649 ComponentName cn = ComponentName.unflattenFromString(name);
5650 if (cn == null) {
5651 if (mParseError == null) {
5652 mParseError = "Bad set name " + name + " in preferred activity "
5653 + mShortActivity;
5654 }
5655 } else {
5656 myPackages[setPos] = cn.getPackageName();
5657 myClasses[setPos] = cn.getClassName();
5658 myComponents[setPos] = name;
5659 setPos++;
5660 }
5661 }
5662 XmlUtils.skipCurrentTag(parser);
5663 } else if (tagName.equals("filter")) {
5664 //Log.i(TAG, "Starting to parse filter...");
5665 readFromXml(parser);
5666 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5667 // + parser.getDepth() + " tag=" + parser.getName());
5668 } else {
5669 reportSettingsProblem(Log.WARN,
5670 "Unknown element under <preferred-activities>: "
5671 + parser.getName());
5672 XmlUtils.skipCurrentTag(parser);
5673 }
5674 }
5675
5676 if (setPos != setCount) {
5677 if (mParseError == null) {
5678 mParseError = "Not enough set tags (expected " + setCount
5679 + " but found " + setPos + ") in " + mShortActivity;
5680 }
5681 }
5682
5683 mSetPackages = myPackages;
5684 mSetClasses = myClasses;
5685 mSetComponents = myComponents;
5686 }
5687
5688 public void writeToXml(XmlSerializer serializer) throws IOException {
5689 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5690 serializer.attribute(null, "name", mShortActivity);
5691 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5692 serializer.attribute(null, "set", Integer.toString(NS));
5693 for (int s=0; s<NS; s++) {
5694 serializer.startTag(null, "set");
5695 serializer.attribute(null, "name", mSetComponents[s]);
5696 serializer.endTag(null, "set");
5697 }
5698 serializer.startTag(null, "filter");
5699 super.writeToXml(serializer);
5700 serializer.endTag(null, "filter");
5701 }
5702
5703 boolean sameSet(List<ResolveInfo> query, int priority) {
5704 if (mSetPackages == null) return false;
5705 final int NQ = query.size();
5706 final int NS = mSetPackages.length;
5707 int numMatch = 0;
5708 for (int i=0; i<NQ; i++) {
5709 ResolveInfo ri = query.get(i);
5710 if (ri.priority != priority) continue;
5711 ActivityInfo ai = ri.activityInfo;
5712 boolean good = false;
5713 for (int j=0; j<NS; j++) {
5714 if (mSetPackages[j].equals(ai.packageName)
5715 && mSetClasses[j].equals(ai.name)) {
5716 numMatch++;
5717 good = true;
5718 break;
5719 }
5720 }
5721 if (!good) return false;
5722 }
5723 return numMatch == NS;
5724 }
5725 }
5726
5727 static class GrantedPermissions {
5728 final int pkgFlags;
5729
5730 HashSet<String> grantedPermissions = new HashSet<String>();
5731 int[] gids;
5732
5733 HashSet<String> loadedPermissions = new HashSet<String>();
5734
5735 GrantedPermissions(int pkgFlags) {
5736 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5737 }
5738 }
5739
5740 /**
5741 * Settings base class for pending and resolved classes.
5742 */
5743 static class PackageSettingBase extends GrantedPermissions {
5744 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005745 File codePath;
5746 String codePathString;
5747 File resourcePath;
5748 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 private long timeStamp;
5750 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005751 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005752
5753 PackageSignatures signatures = new PackageSignatures();
5754
5755 boolean permissionsFixed;
5756
5757 /* Explicitly disabled components */
5758 HashSet<String> disabledComponents = new HashSet<String>(0);
5759 /* Explicitly enabled components */
5760 HashSet<String> enabledComponents = new HashSet<String>(0);
5761 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5762 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005763
5764 /* package name of the app that installed this package */
5765 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005766
5767 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005768 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 super(pkgFlags);
5770 this.name = name;
5771 this.codePath = codePath;
5772 this.codePathString = codePath.toString();
5773 this.resourcePath = resourcePath;
5774 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005775 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 }
5777
Jacek Surazski65e13172009-04-28 15:26:38 +02005778 public void setInstallerPackageName(String packageName) {
5779 installerPackageName = packageName;
5780 }
5781
5782 String getInstallerPackageName() {
5783 return installerPackageName;
5784 }
5785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 public void setInstallStatus(int newStatus) {
5787 installStatus = newStatus;
5788 }
5789
5790 public int getInstallStatus() {
5791 return installStatus;
5792 }
5793
5794 public void setTimeStamp(long newStamp) {
5795 if (newStamp != timeStamp) {
5796 timeStamp = newStamp;
5797 timeStampString = Long.toString(newStamp);
5798 }
5799 }
5800
5801 public void setTimeStamp(long newStamp, String newStampStr) {
5802 timeStamp = newStamp;
5803 timeStampString = newStampStr;
5804 }
5805
5806 public long getTimeStamp() {
5807 return timeStamp;
5808 }
5809
5810 public String getTimeStampStr() {
5811 return timeStampString;
5812 }
5813
5814 public void copyFrom(PackageSettingBase base) {
5815 grantedPermissions = base.grantedPermissions;
5816 gids = base.gids;
5817 loadedPermissions = base.loadedPermissions;
5818
5819 timeStamp = base.timeStamp;
5820 timeStampString = base.timeStampString;
5821 signatures = base.signatures;
5822 permissionsFixed = base.permissionsFixed;
5823 disabledComponents = base.disabledComponents;
5824 enabledComponents = base.enabledComponents;
5825 enabled = base.enabled;
5826 installStatus = base.installStatus;
5827 }
5828
5829 void enableComponentLP(String componentClassName) {
5830 disabledComponents.remove(componentClassName);
5831 enabledComponents.add(componentClassName);
5832 }
5833
5834 void disableComponentLP(String componentClassName) {
5835 enabledComponents.remove(componentClassName);
5836 disabledComponents.add(componentClassName);
5837 }
5838
5839 void restoreComponentLP(String componentClassName) {
5840 enabledComponents.remove(componentClassName);
5841 disabledComponents.remove(componentClassName);
5842 }
5843
5844 int currentEnabledStateLP(String componentName) {
5845 if (enabledComponents.contains(componentName)) {
5846 return COMPONENT_ENABLED_STATE_ENABLED;
5847 } else if (disabledComponents.contains(componentName)) {
5848 return COMPONENT_ENABLED_STATE_DISABLED;
5849 } else {
5850 return COMPONENT_ENABLED_STATE_DEFAULT;
5851 }
5852 }
5853 }
5854
5855 /**
5856 * Settings data for a particular package we know about.
5857 */
5858 static final class PackageSetting extends PackageSettingBase {
5859 int userId;
5860 PackageParser.Package pkg;
5861 SharedUserSetting sharedUser;
5862
5863 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005864 int pVersionCode, int pkgFlags) {
5865 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 }
5867
5868 @Override
5869 public String toString() {
5870 return "PackageSetting{"
5871 + Integer.toHexString(System.identityHashCode(this))
5872 + " " + name + "/" + userId + "}";
5873 }
5874 }
5875
5876 /**
5877 * Settings data for a particular shared user ID we know about.
5878 */
5879 static final class SharedUserSetting extends GrantedPermissions {
5880 final String name;
5881 int userId;
5882 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5883 final PackageSignatures signatures = new PackageSignatures();
5884
5885 SharedUserSetting(String _name, int _pkgFlags) {
5886 super(_pkgFlags);
5887 name = _name;
5888 }
5889
5890 @Override
5891 public String toString() {
5892 return "SharedUserSetting{"
5893 + Integer.toHexString(System.identityHashCode(this))
5894 + " " + name + "/" + userId + "}";
5895 }
5896 }
5897
5898 /**
5899 * Holds information about dynamic settings.
5900 */
5901 private static final class Settings {
5902 private final File mSettingsFilename;
5903 private final File mBackupSettingsFilename;
5904 private final HashMap<String, PackageSetting> mPackages =
5905 new HashMap<String, PackageSetting>();
5906 // The user's preferred packages/applications, in order of preference.
5907 // First is the most preferred.
5908 private final ArrayList<PackageSetting> mPreferredPackages =
5909 new ArrayList<PackageSetting>();
5910 // List of replaced system applications
5911 final HashMap<String, PackageSetting> mDisabledSysPackages =
5912 new HashMap<String, PackageSetting>();
5913
5914 // The user's preferred activities associated with particular intent
5915 // filters.
5916 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5917 new IntentResolver<PreferredActivity, PreferredActivity>() {
5918 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005919 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005921 out.print(prefix); out.print(
5922 Integer.toHexString(System.identityHashCode(filter)));
5923 out.print(' ');
5924 out.print(filter.mActivity.flattenToShortString());
5925 out.print(" match=0x");
5926 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005927 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005928 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005930 out.print(prefix); out.print(" ");
5931 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 }
5933 }
5934 }
5935 };
5936 private final HashMap<String, SharedUserSetting> mSharedUsers =
5937 new HashMap<String, SharedUserSetting>();
5938 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5939 private final SparseArray<Object> mOtherUserIds =
5940 new SparseArray<Object>();
5941
5942 // For reading/writing settings file.
5943 private final ArrayList<Signature> mPastSignatures =
5944 new ArrayList<Signature>();
5945
5946 // Mapping from permission names to info about them.
5947 final HashMap<String, BasePermission> mPermissions =
5948 new HashMap<String, BasePermission>();
5949
5950 // Mapping from permission tree names to info about them.
5951 final HashMap<String, BasePermission> mPermissionTrees =
5952 new HashMap<String, BasePermission>();
5953
5954 private final ArrayList<String> mPendingPreferredPackages
5955 = new ArrayList<String>();
5956
5957 private final StringBuilder mReadMessages = new StringBuilder();
5958
5959 private static final class PendingPackage extends PackageSettingBase {
5960 final int sharedId;
5961
5962 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005963 int sharedId, int pVersionCode, int pkgFlags) {
5964 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 this.sharedId = sharedId;
5966 }
5967 }
5968 private final ArrayList<PendingPackage> mPendingPackages
5969 = new ArrayList<PendingPackage>();
5970
5971 Settings() {
5972 File dataDir = Environment.getDataDirectory();
5973 File systemDir = new File(dataDir, "system");
5974 systemDir.mkdirs();
5975 FileUtils.setPermissions(systemDir.toString(),
5976 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5977 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5978 -1, -1);
5979 mSettingsFilename = new File(systemDir, "packages.xml");
5980 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5981 }
5982
5983 PackageSetting getPackageLP(PackageParser.Package pkg,
5984 SharedUserSetting sharedUser, File codePath, File resourcePath,
5985 int pkgFlags, boolean create, boolean add) {
5986 final String name = pkg.packageName;
5987 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005988 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 return p;
5990 }
5991
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005992 PackageSetting peekPackageLP(String name) {
5993 return mPackages.get(name);
5994 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 PackageSetting p = mPackages.get(name);
5996 if (p != null && p.codePath.getPath().equals(codePath)) {
5997 return p;
5998 }
5999 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006000 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006001 }
6002
6003 void setInstallStatus(String pkgName, int status) {
6004 PackageSetting p = mPackages.get(pkgName);
6005 if(p != null) {
6006 if(p.getInstallStatus() != status) {
6007 p.setInstallStatus(status);
6008 }
6009 }
6010 }
6011
Jacek Surazski65e13172009-04-28 15:26:38 +02006012 void setInstallerPackageName(String pkgName,
6013 String installerPkgName) {
6014 PackageSetting p = mPackages.get(pkgName);
6015 if(p != null) {
6016 p.setInstallerPackageName(installerPkgName);
6017 }
6018 }
6019
6020 String getInstallerPackageName(String pkgName) {
6021 PackageSetting p = mPackages.get(pkgName);
6022 return (p == null) ? null : p.getInstallerPackageName();
6023 }
6024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 int getInstallStatus(String pkgName) {
6026 PackageSetting p = mPackages.get(pkgName);
6027 if(p != null) {
6028 return p.getInstallStatus();
6029 }
6030 return -1;
6031 }
6032
6033 SharedUserSetting getSharedUserLP(String name,
6034 int pkgFlags, boolean create) {
6035 SharedUserSetting s = mSharedUsers.get(name);
6036 if (s == null) {
6037 if (!create) {
6038 return null;
6039 }
6040 s = new SharedUserSetting(name, pkgFlags);
6041 if (MULTIPLE_APPLICATION_UIDS) {
6042 s.userId = newUserIdLP(s);
6043 } else {
6044 s.userId = FIRST_APPLICATION_UID;
6045 }
6046 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6047 // < 0 means we couldn't assign a userid; fall out and return
6048 // s, which is currently null
6049 if (s.userId >= 0) {
6050 mSharedUsers.put(name, s);
6051 }
6052 }
6053
6054 return s;
6055 }
6056
6057 int disableSystemPackageLP(String name) {
6058 PackageSetting p = mPackages.get(name);
6059 if(p == null) {
6060 Log.w(TAG, "Package:"+name+" is not an installed package");
6061 return -1;
6062 }
6063 PackageSetting dp = mDisabledSysPackages.get(name);
6064 // always make sure the system package code and resource paths dont change
6065 if(dp == null) {
6066 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6067 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6068 }
6069 mDisabledSysPackages.put(name, p);
6070 }
6071 return removePackageLP(name);
6072 }
6073
6074 PackageSetting enableSystemPackageLP(String name) {
6075 PackageSetting p = mDisabledSysPackages.get(name);
6076 if(p == null) {
6077 Log.w(TAG, "Package:"+name+" is not disabled");
6078 return null;
6079 }
6080 // Reset flag in ApplicationInfo object
6081 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6082 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6083 }
6084 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006085 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 mDisabledSysPackages.remove(name);
6087 return ret;
6088 }
6089
6090 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006091 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 PackageSetting p = mPackages.get(name);
6093 if (p != null) {
6094 if (p.userId == uid) {
6095 return p;
6096 }
6097 reportSettingsProblem(Log.ERROR,
6098 "Adding duplicate package, keeping first: " + name);
6099 return null;
6100 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006101 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 p.userId = uid;
6103 if (addUserIdLP(uid, p, name)) {
6104 mPackages.put(name, p);
6105 return p;
6106 }
6107 return null;
6108 }
6109
6110 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6111 SharedUserSetting s = mSharedUsers.get(name);
6112 if (s != null) {
6113 if (s.userId == uid) {
6114 return s;
6115 }
6116 reportSettingsProblem(Log.ERROR,
6117 "Adding duplicate shared user, keeping first: " + name);
6118 return null;
6119 }
6120 s = new SharedUserSetting(name, pkgFlags);
6121 s.userId = uid;
6122 if (addUserIdLP(uid, s, name)) {
6123 mSharedUsers.put(name, s);
6124 return s;
6125 }
6126 return null;
6127 }
6128
6129 private PackageSetting getPackageLP(String name,
6130 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006131 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 PackageSetting p = mPackages.get(name);
6133 if (p != null) {
6134 if (!p.codePath.equals(codePath)) {
6135 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006136 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006137 // This is an updated system app with versions in both system
6138 // and data partition. Just let the most recent version
6139 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006140 Log.w(TAG, "Trying to update system app code path from " +
6141 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006142 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006143 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006144 reportSettingsProblem(Log.WARN,
6145 "Package " + name + " codePath changed from " + p.codePath
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006146 + " to " + codePath + "; Retaining data and using new code from " +
6147 codePath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 }
6149 } else if (p.sharedUser != sharedUser) {
6150 reportSettingsProblem(Log.WARN,
6151 "Package " + name + " shared user changed from "
6152 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6153 + " to "
6154 + (sharedUser != null ? sharedUser.name : "<nothing>")
6155 + "; replacing with new");
6156 p = null;
6157 }
6158 }
6159 if (p == null) {
6160 // Create a new PackageSettings entry. this can end up here because
6161 // of code path mismatch or user id mismatch of an updated system partition
6162 if (!create) {
6163 return null;
6164 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006165 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006166 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006167 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 if (sharedUser != null) {
6169 p.userId = sharedUser.userId;
6170 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006171 // Clone the setting here for disabled system packages
6172 PackageSetting dis = mDisabledSysPackages.get(name);
6173 if (dis != null) {
6174 // For disabled packages a new setting is created
6175 // from the existing user id. This still has to be
6176 // added to list of user id's
6177 // Copy signatures from previous setting
6178 if (dis.signatures.mSignatures != null) {
6179 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6180 }
6181 p.userId = dis.userId;
6182 // Clone permissions
6183 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6184 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6185 // Clone component info
6186 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6187 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6188 // Add new setting to list of user ids
6189 addUserIdLP(p.userId, p, name);
6190 } else {
6191 // Assign new user id
6192 p.userId = newUserIdLP(p);
6193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006194 } else {
6195 p.userId = FIRST_APPLICATION_UID;
6196 }
6197 if (p.userId < 0) {
6198 reportSettingsProblem(Log.WARN,
6199 "Package " + name + " could not be assigned a valid uid");
6200 return null;
6201 }
6202 if (add) {
6203 // Finish adding new package by adding it and updating shared
6204 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006205 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
6207 }
6208 return p;
6209 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006210
6211 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6212 File codePath, File resourcePath) {
6213 p.pkg = pkg;
6214 // Update code path if needed
6215 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6216 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
6217 " changing form " + p.codePathString + " to " + codePath);
6218 p.codePath = codePath;
6219 p.codePathString = codePath.toString();
6220 }
6221 //Update resource path if needed
6222 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6223 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
6224 " changing form " + p.resourcePathString + " to " + resourcePath);
6225 p.resourcePath = resourcePath;
6226 p.resourcePathString = resourcePath.toString();
6227 }
6228 // Update version code if needed
6229 if (pkg.mVersionCode != p.versionCode) {
6230 p.versionCode = pkg.mVersionCode;
6231 }
6232 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6233 }
6234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006235 // Utility method that adds a PackageSetting to mPackages and
6236 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006237 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006238 SharedUserSetting sharedUser) {
6239 mPackages.put(name, p);
6240 if (sharedUser != null) {
6241 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6242 reportSettingsProblem(Log.ERROR,
6243 "Package " + p.name + " was user "
6244 + p.sharedUser + " but is now " + sharedUser
6245 + "; I am not changing its files so it will probably fail!");
6246 p.sharedUser.packages.remove(p);
6247 } else if (p.userId != sharedUser.userId) {
6248 reportSettingsProblem(Log.ERROR,
6249 "Package " + p.name + " was user id " + p.userId
6250 + " but is now user " + sharedUser
6251 + " with id " + sharedUser.userId
6252 + "; I am not changing its files so it will probably fail!");
6253 }
6254
6255 sharedUser.packages.add(p);
6256 p.sharedUser = sharedUser;
6257 p.userId = sharedUser.userId;
6258 }
6259 }
6260
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006261 /*
6262 * Update the shared user setting when a package using
6263 * specifying the shared user id is removed. The gids
6264 * associated with each permission of the deleted package
6265 * are removed from the shared user's gid list only if its
6266 * not in use by other permissions of packages in the
6267 * shared user setting.
6268 */
6269 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6271 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6272 return;
6273 }
6274 // No sharedUserId
6275 if (deletedPs.sharedUser == null) {
6276 return;
6277 }
6278 SharedUserSetting sus = deletedPs.sharedUser;
6279 // Update permissions
6280 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6281 boolean used = false;
6282 if (!sus.grantedPermissions.contains (eachPerm)) {
6283 continue;
6284 }
6285 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapub97b8f82009-06-19 15:09:18 -07006286 if (pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 used = true;
6288 break;
6289 }
6290 }
6291 if (!used) {
6292 // can safely delete this permission from list
6293 sus.grantedPermissions.remove(eachPerm);
6294 sus.loadedPermissions.remove(eachPerm);
6295 }
6296 }
6297 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006298 int newGids[] = globalGids;
6299 for (String eachPerm : sus.grantedPermissions) {
6300 BasePermission bp = mPermissions.get(eachPerm);
6301 newGids = appendInts(newGids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 }
6303 sus.gids = newGids;
6304 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 private int removePackageLP(String name) {
6307 PackageSetting p = mPackages.get(name);
6308 if (p != null) {
6309 mPackages.remove(name);
6310 if (p.sharedUser != null) {
6311 p.sharedUser.packages.remove(p);
6312 if (p.sharedUser.packages.size() == 0) {
6313 mSharedUsers.remove(p.sharedUser.name);
6314 removeUserIdLP(p.sharedUser.userId);
6315 return p.sharedUser.userId;
6316 }
6317 } else {
6318 removeUserIdLP(p.userId);
6319 return p.userId;
6320 }
6321 }
6322 return -1;
6323 }
6324
6325 private boolean addUserIdLP(int uid, Object obj, Object name) {
6326 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6327 return false;
6328 }
6329
6330 if (uid >= FIRST_APPLICATION_UID) {
6331 int N = mUserIds.size();
6332 final int index = uid - FIRST_APPLICATION_UID;
6333 while (index >= N) {
6334 mUserIds.add(null);
6335 N++;
6336 }
6337 if (mUserIds.get(index) != null) {
6338 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006339 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006340 + " name=" + name);
6341 return false;
6342 }
6343 mUserIds.set(index, obj);
6344 } else {
6345 if (mOtherUserIds.get(uid) != null) {
6346 reportSettingsProblem(Log.ERROR,
6347 "Adding duplicate shared id: " + uid
6348 + " name=" + name);
6349 return false;
6350 }
6351 mOtherUserIds.put(uid, obj);
6352 }
6353 return true;
6354 }
6355
6356 public Object getUserIdLP(int uid) {
6357 if (uid >= FIRST_APPLICATION_UID) {
6358 int N = mUserIds.size();
6359 final int index = uid - FIRST_APPLICATION_UID;
6360 return index < N ? mUserIds.get(index) : null;
6361 } else {
6362 return mOtherUserIds.get(uid);
6363 }
6364 }
6365
6366 private void removeUserIdLP(int uid) {
6367 if (uid >= FIRST_APPLICATION_UID) {
6368 int N = mUserIds.size();
6369 final int index = uid - FIRST_APPLICATION_UID;
6370 if (index < N) mUserIds.set(index, null);
6371 } else {
6372 mOtherUserIds.remove(uid);
6373 }
6374 }
6375
6376 void writeLP() {
6377 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6378
6379 // Keep the old settings around until we know the new ones have
6380 // been successfully written.
6381 if (mSettingsFilename.exists()) {
6382 if (mBackupSettingsFilename.exists()) {
6383 mBackupSettingsFilename.delete();
6384 }
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006385 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6386 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6387 return;
6388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006389 }
6390
6391 mPastSignatures.clear();
6392
6393 try {
6394 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6395
6396 //XmlSerializer serializer = XmlUtils.serializerInstance();
6397 XmlSerializer serializer = new FastXmlSerializer();
6398 serializer.setOutput(str, "utf-8");
6399 serializer.startDocument(null, true);
6400 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6401
6402 serializer.startTag(null, "packages");
6403
6404 serializer.startTag(null, "permission-trees");
6405 for (BasePermission bp : mPermissionTrees.values()) {
6406 writePermission(serializer, bp);
6407 }
6408 serializer.endTag(null, "permission-trees");
6409
6410 serializer.startTag(null, "permissions");
6411 for (BasePermission bp : mPermissions.values()) {
6412 writePermission(serializer, bp);
6413 }
6414 serializer.endTag(null, "permissions");
6415
6416 for (PackageSetting pkg : mPackages.values()) {
6417 writePackage(serializer, pkg);
6418 }
6419
6420 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6421 writeDisabledSysPackage(serializer, pkg);
6422 }
6423
6424 serializer.startTag(null, "preferred-packages");
6425 int N = mPreferredPackages.size();
6426 for (int i=0; i<N; i++) {
6427 PackageSetting pkg = mPreferredPackages.get(i);
6428 serializer.startTag(null, "item");
6429 serializer.attribute(null, "name", pkg.name);
6430 serializer.endTag(null, "item");
6431 }
6432 serializer.endTag(null, "preferred-packages");
6433
6434 serializer.startTag(null, "preferred-activities");
6435 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6436 serializer.startTag(null, "item");
6437 pa.writeToXml(serializer);
6438 serializer.endTag(null, "item");
6439 }
6440 serializer.endTag(null, "preferred-activities");
6441
6442 for (SharedUserSetting usr : mSharedUsers.values()) {
6443 serializer.startTag(null, "shared-user");
6444 serializer.attribute(null, "name", usr.name);
6445 serializer.attribute(null, "userId",
6446 Integer.toString(usr.userId));
6447 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6448 serializer.startTag(null, "perms");
6449 for (String name : usr.grantedPermissions) {
6450 serializer.startTag(null, "item");
6451 serializer.attribute(null, "name", name);
6452 serializer.endTag(null, "item");
6453 }
6454 serializer.endTag(null, "perms");
6455 serializer.endTag(null, "shared-user");
6456 }
6457
6458 serializer.endTag(null, "packages");
6459
6460 serializer.endDocument();
6461
6462 str.flush();
6463 str.close();
6464
6465 // New settings successfully written, old ones are no longer
6466 // needed.
6467 mBackupSettingsFilename.delete();
6468 FileUtils.setPermissions(mSettingsFilename.toString(),
6469 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6470 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6471 |FileUtils.S_IROTH,
6472 -1, -1);
6473
6474 } catch(XmlPullParserException e) {
6475 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
6476
6477 } catch(java.io.IOException e) {
6478 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
6479
6480 }
6481
6482 //Debug.stopMethodTracing();
6483 }
6484
6485 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
6486 throws java.io.IOException {
6487 serializer.startTag(null, "updated-package");
6488 serializer.attribute(null, "name", pkg.name);
6489 serializer.attribute(null, "codePath", pkg.codePathString);
6490 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006491 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006492 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6493 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6494 }
6495 if (pkg.sharedUser == null) {
6496 serializer.attribute(null, "userId",
6497 Integer.toString(pkg.userId));
6498 } else {
6499 serializer.attribute(null, "sharedUserId",
6500 Integer.toString(pkg.userId));
6501 }
6502 serializer.startTag(null, "perms");
6503 if (pkg.sharedUser == null) {
6504 // If this is a shared user, the permissions will
6505 // be written there. We still need to write an
6506 // empty permissions list so permissionsFixed will
6507 // be set.
6508 for (final String name : pkg.grantedPermissions) {
6509 BasePermission bp = mPermissions.get(name);
6510 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6511 // We only need to write signature or system permissions but this wont
6512 // match the semantics of grantedPermissions. So write all permissions.
6513 serializer.startTag(null, "item");
6514 serializer.attribute(null, "name", name);
6515 serializer.endTag(null, "item");
6516 }
6517 }
6518 }
6519 serializer.endTag(null, "perms");
6520 serializer.endTag(null, "updated-package");
6521 }
6522
6523 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6524 throws java.io.IOException {
6525 serializer.startTag(null, "package");
6526 serializer.attribute(null, "name", pkg.name);
6527 serializer.attribute(null, "codePath", pkg.codePathString);
6528 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6529 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6530 }
6531 serializer.attribute(null, "system",
6532 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6533 ? "true" : "false");
6534 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006535 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 if (pkg.sharedUser == null) {
6537 serializer.attribute(null, "userId",
6538 Integer.toString(pkg.userId));
6539 } else {
6540 serializer.attribute(null, "sharedUserId",
6541 Integer.toString(pkg.userId));
6542 }
6543 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6544 serializer.attribute(null, "enabled",
6545 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6546 ? "true" : "false");
6547 }
6548 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6549 serializer.attribute(null, "installStatus", "false");
6550 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006551 if (pkg.installerPackageName != null) {
6552 serializer.attribute(null, "installer", pkg.installerPackageName);
6553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006554 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6555 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6556 serializer.startTag(null, "perms");
6557 if (pkg.sharedUser == null) {
6558 // If this is a shared user, the permissions will
6559 // be written there. We still need to write an
6560 // empty permissions list so permissionsFixed will
6561 // be set.
6562 for (final String name : pkg.grantedPermissions) {
6563 serializer.startTag(null, "item");
6564 serializer.attribute(null, "name", name);
6565 serializer.endTag(null, "item");
6566 }
6567 }
6568 serializer.endTag(null, "perms");
6569 }
6570 if (pkg.disabledComponents.size() > 0) {
6571 serializer.startTag(null, "disabled-components");
6572 for (final String name : pkg.disabledComponents) {
6573 serializer.startTag(null, "item");
6574 serializer.attribute(null, "name", name);
6575 serializer.endTag(null, "item");
6576 }
6577 serializer.endTag(null, "disabled-components");
6578 }
6579 if (pkg.enabledComponents.size() > 0) {
6580 serializer.startTag(null, "enabled-components");
6581 for (final String name : pkg.enabledComponents) {
6582 serializer.startTag(null, "item");
6583 serializer.attribute(null, "name", name);
6584 serializer.endTag(null, "item");
6585 }
6586 serializer.endTag(null, "enabled-components");
6587 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 serializer.endTag(null, "package");
6590 }
6591
6592 void writePermission(XmlSerializer serializer, BasePermission bp)
6593 throws XmlPullParserException, java.io.IOException {
6594 if (bp.type != BasePermission.TYPE_BUILTIN
6595 && bp.sourcePackage != null) {
6596 serializer.startTag(null, "item");
6597 serializer.attribute(null, "name", bp.name);
6598 serializer.attribute(null, "package", bp.sourcePackage);
6599 if (DEBUG_SETTINGS) Log.v(TAG,
6600 "Writing perm: name=" + bp.name + " type=" + bp.type);
6601 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6602 PermissionInfo pi = bp.perm != null ? bp.perm.info
6603 : bp.pendingInfo;
6604 if (pi != null) {
6605 serializer.attribute(null, "type", "dynamic");
6606 if (pi.icon != 0) {
6607 serializer.attribute(null, "icon",
6608 Integer.toString(pi.icon));
6609 }
6610 if (pi.nonLocalizedLabel != null) {
6611 serializer.attribute(null, "label",
6612 pi.nonLocalizedLabel.toString());
6613 }
6614 if (pi.protectionLevel !=
6615 PermissionInfo.PROTECTION_NORMAL) {
6616 serializer.attribute(null, "protection",
6617 Integer.toString(pi.protectionLevel));
6618 }
6619 }
6620 }
6621 serializer.endTag(null, "item");
6622 }
6623 }
6624
6625 String getReadMessagesLP() {
6626 return mReadMessages.toString();
6627 }
6628
6629 ArrayList<String> getListOfIncompleteInstallPackages() {
6630 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6631 Iterator<String> its = kList.iterator();
6632 ArrayList<String> ret = new ArrayList<String>();
6633 while(its.hasNext()) {
6634 String key = its.next();
6635 PackageSetting ps = mPackages.get(key);
6636 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6637 ret.add(key);
6638 }
6639 }
6640 return ret;
6641 }
6642
6643 boolean readLP() {
6644 FileInputStream str = null;
6645 if (mBackupSettingsFilename.exists()) {
6646 try {
6647 str = new FileInputStream(mBackupSettingsFilename);
6648 mReadMessages.append("Reading from backup settings file\n");
6649 Log.i(TAG, "Reading from backup settings file!");
6650 } catch (java.io.IOException e) {
6651 // We'll try for the normal settings file.
6652 }
6653 }
6654
6655 mPastSignatures.clear();
6656
6657 try {
6658 if (str == null) {
6659 if (!mSettingsFilename.exists()) {
6660 mReadMessages.append("No settings file found\n");
6661 Log.i(TAG, "No current settings file!");
6662 return false;
6663 }
6664 str = new FileInputStream(mSettingsFilename);
6665 }
6666 XmlPullParser parser = Xml.newPullParser();
6667 parser.setInput(str, null);
6668
6669 int type;
6670 while ((type=parser.next()) != XmlPullParser.START_TAG
6671 && type != XmlPullParser.END_DOCUMENT) {
6672 ;
6673 }
6674
6675 if (type != XmlPullParser.START_TAG) {
6676 mReadMessages.append("No start tag found in settings file\n");
6677 Log.e(TAG, "No start tag found in package manager settings");
6678 return false;
6679 }
6680
6681 int outerDepth = parser.getDepth();
6682 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6683 && (type != XmlPullParser.END_TAG
6684 || parser.getDepth() > outerDepth)) {
6685 if (type == XmlPullParser.END_TAG
6686 || type == XmlPullParser.TEXT) {
6687 continue;
6688 }
6689
6690 String tagName = parser.getName();
6691 if (tagName.equals("package")) {
6692 readPackageLP(parser);
6693 } else if (tagName.equals("permissions")) {
6694 readPermissionsLP(mPermissions, parser);
6695 } else if (tagName.equals("permission-trees")) {
6696 readPermissionsLP(mPermissionTrees, parser);
6697 } else if (tagName.equals("shared-user")) {
6698 readSharedUserLP(parser);
6699 } else if (tagName.equals("preferred-packages")) {
6700 readPreferredPackagesLP(parser);
6701 } else if (tagName.equals("preferred-activities")) {
6702 readPreferredActivitiesLP(parser);
6703 } else if(tagName.equals("updated-package")) {
6704 readDisabledSysPackageLP(parser);
6705 } else {
6706 Log.w(TAG, "Unknown element under <packages>: "
6707 + parser.getName());
6708 XmlUtils.skipCurrentTag(parser);
6709 }
6710 }
6711
6712 str.close();
6713
6714 } catch(XmlPullParserException e) {
6715 mReadMessages.append("Error reading: " + e.toString());
6716 Log.e(TAG, "Error reading package manager settings", e);
6717
6718 } catch(java.io.IOException e) {
6719 mReadMessages.append("Error reading: " + e.toString());
6720 Log.e(TAG, "Error reading package manager settings", e);
6721
6722 }
6723
6724 int N = mPendingPackages.size();
6725 for (int i=0; i<N; i++) {
6726 final PendingPackage pp = mPendingPackages.get(i);
6727 Object idObj = getUserIdLP(pp.sharedId);
6728 if (idObj != null && idObj instanceof SharedUserSetting) {
6729 PackageSetting p = getPackageLP(pp.name,
6730 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006731 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 if (p == null) {
6733 Log.w(TAG, "Unable to create application package for "
6734 + pp.name);
6735 continue;
6736 }
6737 p.copyFrom(pp);
6738 } else if (idObj != null) {
6739 String msg = "Bad package setting: package " + pp.name
6740 + " has shared uid " + pp.sharedId
6741 + " that is not a shared uid\n";
6742 mReadMessages.append(msg);
6743 Log.e(TAG, msg);
6744 } else {
6745 String msg = "Bad package setting: package " + pp.name
6746 + " has shared uid " + pp.sharedId
6747 + " that is not defined\n";
6748 mReadMessages.append(msg);
6749 Log.e(TAG, msg);
6750 }
6751 }
6752 mPendingPackages.clear();
6753
6754 N = mPendingPreferredPackages.size();
6755 mPreferredPackages.clear();
6756 for (int i=0; i<N; i++) {
6757 final String name = mPendingPreferredPackages.get(i);
6758 final PackageSetting p = mPackages.get(name);
6759 if (p != null) {
6760 mPreferredPackages.add(p);
6761 } else {
6762 Log.w(TAG, "Unknown preferred package: " + name);
6763 }
6764 }
6765 mPendingPreferredPackages.clear();
6766
6767 mReadMessages.append("Read completed successfully: "
6768 + mPackages.size() + " packages, "
6769 + mSharedUsers.size() + " shared uids\n");
6770
6771 return true;
6772 }
6773
6774 private int readInt(XmlPullParser parser, String ns, String name,
6775 int defValue) {
6776 String v = parser.getAttributeValue(ns, name);
6777 try {
6778 if (v == null) {
6779 return defValue;
6780 }
6781 return Integer.parseInt(v);
6782 } catch (NumberFormatException e) {
6783 reportSettingsProblem(Log.WARN,
6784 "Error in package manager settings: attribute " +
6785 name + " has bad integer value " + v + " at "
6786 + parser.getPositionDescription());
6787 }
6788 return defValue;
6789 }
6790
6791 private void readPermissionsLP(HashMap<String, BasePermission> out,
6792 XmlPullParser parser)
6793 throws IOException, XmlPullParserException {
6794 int outerDepth = parser.getDepth();
6795 int type;
6796 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6797 && (type != XmlPullParser.END_TAG
6798 || parser.getDepth() > outerDepth)) {
6799 if (type == XmlPullParser.END_TAG
6800 || type == XmlPullParser.TEXT) {
6801 continue;
6802 }
6803
6804 String tagName = parser.getName();
6805 if (tagName.equals("item")) {
6806 String name = parser.getAttributeValue(null, "name");
6807 String sourcePackage = parser.getAttributeValue(null, "package");
6808 String ptype = parser.getAttributeValue(null, "type");
6809 if (name != null && sourcePackage != null) {
6810 boolean dynamic = "dynamic".equals(ptype);
6811 BasePermission bp = new BasePermission(name, sourcePackage,
6812 dynamic
6813 ? BasePermission.TYPE_DYNAMIC
6814 : BasePermission.TYPE_NORMAL);
6815 if (dynamic) {
6816 PermissionInfo pi = new PermissionInfo();
6817 pi.packageName = sourcePackage.intern();
6818 pi.name = name.intern();
6819 pi.icon = readInt(parser, null, "icon", 0);
6820 pi.nonLocalizedLabel = parser.getAttributeValue(
6821 null, "label");
6822 pi.protectionLevel = readInt(parser, null, "protection",
6823 PermissionInfo.PROTECTION_NORMAL);
6824 bp.pendingInfo = pi;
6825 }
6826 out.put(bp.name, bp);
6827 } else {
6828 reportSettingsProblem(Log.WARN,
6829 "Error in package manager settings: permissions has"
6830 + " no name at " + parser.getPositionDescription());
6831 }
6832 } else {
6833 reportSettingsProblem(Log.WARN,
6834 "Unknown element reading permissions: "
6835 + parser.getName() + " at "
6836 + parser.getPositionDescription());
6837 }
6838 XmlUtils.skipCurrentTag(parser);
6839 }
6840 }
6841
6842 private void readDisabledSysPackageLP(XmlPullParser parser)
6843 throws XmlPullParserException, IOException {
6844 String name = parser.getAttributeValue(null, "name");
6845 String codePathStr = parser.getAttributeValue(null, "codePath");
6846 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6847 if(resourcePathStr == null) {
6848 resourcePathStr = codePathStr;
6849 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006850 String version = parser.getAttributeValue(null, "version");
6851 int versionCode = 0;
6852 if (version != null) {
6853 try {
6854 versionCode = Integer.parseInt(version);
6855 } catch (NumberFormatException e) {
6856 }
6857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858
6859 int pkgFlags = 0;
6860 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6861 PackageSetting ps = new PackageSetting(name,
6862 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006863 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864 String timeStampStr = parser.getAttributeValue(null, "ts");
6865 if (timeStampStr != null) {
6866 try {
6867 long timeStamp = Long.parseLong(timeStampStr);
6868 ps.setTimeStamp(timeStamp, timeStampStr);
6869 } catch (NumberFormatException e) {
6870 }
6871 }
6872 String idStr = parser.getAttributeValue(null, "userId");
6873 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6874 if(ps.userId <= 0) {
6875 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6876 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6877 }
6878 int outerDepth = parser.getDepth();
6879 int type;
6880 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6881 && (type != XmlPullParser.END_TAG
6882 || parser.getDepth() > outerDepth)) {
6883 if (type == XmlPullParser.END_TAG
6884 || type == XmlPullParser.TEXT) {
6885 continue;
6886 }
6887
6888 String tagName = parser.getName();
6889 if (tagName.equals("perms")) {
6890 readGrantedPermissionsLP(parser,
6891 ps.grantedPermissions);
6892 } else {
6893 reportSettingsProblem(Log.WARN,
6894 "Unknown element under <updated-package>: "
6895 + parser.getName());
6896 XmlUtils.skipCurrentTag(parser);
6897 }
6898 }
6899 mDisabledSysPackages.put(name, ps);
6900 }
6901
6902 private void readPackageLP(XmlPullParser parser)
6903 throws XmlPullParserException, IOException {
6904 String name = null;
6905 String idStr = null;
6906 String sharedIdStr = null;
6907 String codePathStr = null;
6908 String resourcePathStr = null;
6909 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02006910 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 int pkgFlags = 0;
6912 String timeStampStr;
6913 long timeStamp = 0;
6914 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006915 String version = null;
6916 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006917 try {
6918 name = parser.getAttributeValue(null, "name");
6919 idStr = parser.getAttributeValue(null, "userId");
6920 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6921 codePathStr = parser.getAttributeValue(null, "codePath");
6922 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006923 version = parser.getAttributeValue(null, "version");
6924 if (version != null) {
6925 try {
6926 versionCode = Integer.parseInt(version);
6927 } catch (NumberFormatException e) {
6928 }
6929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02006931 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006932 if (systemStr != null) {
6933 if ("true".equals(systemStr)) {
6934 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6935 }
6936 } else {
6937 // Old settings that don't specify system... just treat
6938 // them as system, good enough.
6939 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6940 }
6941 timeStampStr = parser.getAttributeValue(null, "ts");
6942 if (timeStampStr != null) {
6943 try {
6944 timeStamp = Long.parseLong(timeStampStr);
6945 } catch (NumberFormatException e) {
6946 }
6947 }
6948 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6949 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6950 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6951 if (resourcePathStr == null) {
6952 resourcePathStr = codePathStr;
6953 }
6954 if (name == null) {
6955 reportSettingsProblem(Log.WARN,
6956 "Error in package manager settings: <package> has no name at "
6957 + parser.getPositionDescription());
6958 } else if (codePathStr == null) {
6959 reportSettingsProblem(Log.WARN,
6960 "Error in package manager settings: <package> has no codePath at "
6961 + parser.getPositionDescription());
6962 } else if (userId > 0) {
6963 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006964 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6966 + ": userId=" + userId + " pkg=" + packageSetting);
6967 if (packageSetting == null) {
6968 reportSettingsProblem(Log.ERROR,
6969 "Failure adding uid " + userId
6970 + " while parsing settings at "
6971 + parser.getPositionDescription());
6972 } else {
6973 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6974 }
6975 } else if (sharedIdStr != null) {
6976 userId = sharedIdStr != null
6977 ? Integer.parseInt(sharedIdStr) : 0;
6978 if (userId > 0) {
6979 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006980 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006981 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6982 mPendingPackages.add((PendingPackage) packageSetting);
6983 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6984 + ": sharedUserId=" + userId + " pkg="
6985 + packageSetting);
6986 } else {
6987 reportSettingsProblem(Log.WARN,
6988 "Error in package manager settings: package "
6989 + name + " has bad sharedId " + sharedIdStr
6990 + " at " + parser.getPositionDescription());
6991 }
6992 } else {
6993 reportSettingsProblem(Log.WARN,
6994 "Error in package manager settings: package "
6995 + name + " has bad userId " + idStr + " at "
6996 + parser.getPositionDescription());
6997 }
6998 } catch (NumberFormatException e) {
6999 reportSettingsProblem(Log.WARN,
7000 "Error in package manager settings: package "
7001 + name + " has bad userId " + idStr + " at "
7002 + parser.getPositionDescription());
7003 }
7004 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007005 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 final String enabledStr = parser.getAttributeValue(null, "enabled");
7007 if (enabledStr != null) {
7008 if (enabledStr.equalsIgnoreCase("true")) {
7009 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7010 } else if (enabledStr.equalsIgnoreCase("false")) {
7011 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7012 } else if (enabledStr.equalsIgnoreCase("default")) {
7013 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7014 } else {
7015 reportSettingsProblem(Log.WARN,
7016 "Error in package manager settings: package "
7017 + name + " has bad enabled value: " + idStr
7018 + " at " + parser.getPositionDescription());
7019 }
7020 } else {
7021 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7022 }
7023 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7024 if (installStatusStr != null) {
7025 if (installStatusStr.equalsIgnoreCase("false")) {
7026 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7027 } else {
7028 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7029 }
7030 }
7031
7032 int outerDepth = parser.getDepth();
7033 int type;
7034 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7035 && (type != XmlPullParser.END_TAG
7036 || parser.getDepth() > outerDepth)) {
7037 if (type == XmlPullParser.END_TAG
7038 || type == XmlPullParser.TEXT) {
7039 continue;
7040 }
7041
7042 String tagName = parser.getName();
7043 if (tagName.equals("disabled-components")) {
7044 readDisabledComponentsLP(packageSetting, parser);
7045 } else if (tagName.equals("enabled-components")) {
7046 readEnabledComponentsLP(packageSetting, parser);
7047 } else if (tagName.equals("sigs")) {
7048 packageSetting.signatures.readXml(parser, mPastSignatures);
7049 } else if (tagName.equals("perms")) {
7050 readGrantedPermissionsLP(parser,
7051 packageSetting.loadedPermissions);
7052 packageSetting.permissionsFixed = true;
7053 } else {
7054 reportSettingsProblem(Log.WARN,
7055 "Unknown element under <package>: "
7056 + parser.getName());
7057 XmlUtils.skipCurrentTag(parser);
7058 }
7059 }
7060 } else {
7061 XmlUtils.skipCurrentTag(parser);
7062 }
7063 }
7064
7065 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7066 XmlPullParser parser)
7067 throws IOException, XmlPullParserException {
7068 int outerDepth = parser.getDepth();
7069 int type;
7070 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7071 && (type != XmlPullParser.END_TAG
7072 || parser.getDepth() > outerDepth)) {
7073 if (type == XmlPullParser.END_TAG
7074 || type == XmlPullParser.TEXT) {
7075 continue;
7076 }
7077
7078 String tagName = parser.getName();
7079 if (tagName.equals("item")) {
7080 String name = parser.getAttributeValue(null, "name");
7081 if (name != null) {
7082 packageSetting.disabledComponents.add(name.intern());
7083 } else {
7084 reportSettingsProblem(Log.WARN,
7085 "Error in package manager settings: <disabled-components> has"
7086 + " no name at " + parser.getPositionDescription());
7087 }
7088 } else {
7089 reportSettingsProblem(Log.WARN,
7090 "Unknown element under <disabled-components>: "
7091 + parser.getName());
7092 }
7093 XmlUtils.skipCurrentTag(parser);
7094 }
7095 }
7096
7097 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7098 XmlPullParser parser)
7099 throws IOException, XmlPullParserException {
7100 int outerDepth = parser.getDepth();
7101 int type;
7102 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7103 && (type != XmlPullParser.END_TAG
7104 || parser.getDepth() > outerDepth)) {
7105 if (type == XmlPullParser.END_TAG
7106 || type == XmlPullParser.TEXT) {
7107 continue;
7108 }
7109
7110 String tagName = parser.getName();
7111 if (tagName.equals("item")) {
7112 String name = parser.getAttributeValue(null, "name");
7113 if (name != null) {
7114 packageSetting.enabledComponents.add(name.intern());
7115 } else {
7116 reportSettingsProblem(Log.WARN,
7117 "Error in package manager settings: <enabled-components> has"
7118 + " no name at " + parser.getPositionDescription());
7119 }
7120 } else {
7121 reportSettingsProblem(Log.WARN,
7122 "Unknown element under <enabled-components>: "
7123 + parser.getName());
7124 }
7125 XmlUtils.skipCurrentTag(parser);
7126 }
7127 }
7128
7129 private void readSharedUserLP(XmlPullParser parser)
7130 throws XmlPullParserException, IOException {
7131 String name = null;
7132 String idStr = null;
7133 int pkgFlags = 0;
7134 SharedUserSetting su = null;
7135 try {
7136 name = parser.getAttributeValue(null, "name");
7137 idStr = parser.getAttributeValue(null, "userId");
7138 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7139 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7140 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7141 }
7142 if (name == null) {
7143 reportSettingsProblem(Log.WARN,
7144 "Error in package manager settings: <shared-user> has no name at "
7145 + parser.getPositionDescription());
7146 } else if (userId == 0) {
7147 reportSettingsProblem(Log.WARN,
7148 "Error in package manager settings: shared-user "
7149 + name + " has bad userId " + idStr + " at "
7150 + parser.getPositionDescription());
7151 } else {
7152 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7153 reportSettingsProblem(Log.ERROR,
7154 "Occurred while parsing settings at "
7155 + parser.getPositionDescription());
7156 }
7157 }
7158 } catch (NumberFormatException e) {
7159 reportSettingsProblem(Log.WARN,
7160 "Error in package manager settings: package "
7161 + name + " has bad userId " + idStr + " at "
7162 + parser.getPositionDescription());
7163 };
7164
7165 if (su != null) {
7166 int outerDepth = parser.getDepth();
7167 int type;
7168 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7169 && (type != XmlPullParser.END_TAG
7170 || parser.getDepth() > outerDepth)) {
7171 if (type == XmlPullParser.END_TAG
7172 || type == XmlPullParser.TEXT) {
7173 continue;
7174 }
7175
7176 String tagName = parser.getName();
7177 if (tagName.equals("sigs")) {
7178 su.signatures.readXml(parser, mPastSignatures);
7179 } else if (tagName.equals("perms")) {
7180 readGrantedPermissionsLP(parser, su.loadedPermissions);
7181 } else {
7182 reportSettingsProblem(Log.WARN,
7183 "Unknown element under <shared-user>: "
7184 + parser.getName());
7185 XmlUtils.skipCurrentTag(parser);
7186 }
7187 }
7188
7189 } else {
7190 XmlUtils.skipCurrentTag(parser);
7191 }
7192 }
7193
7194 private void readGrantedPermissionsLP(XmlPullParser parser,
7195 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7196 int outerDepth = parser.getDepth();
7197 int type;
7198 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7199 && (type != XmlPullParser.END_TAG
7200 || parser.getDepth() > outerDepth)) {
7201 if (type == XmlPullParser.END_TAG
7202 || type == XmlPullParser.TEXT) {
7203 continue;
7204 }
7205
7206 String tagName = parser.getName();
7207 if (tagName.equals("item")) {
7208 String name = parser.getAttributeValue(null, "name");
7209 if (name != null) {
7210 outPerms.add(name.intern());
7211 } else {
7212 reportSettingsProblem(Log.WARN,
7213 "Error in package manager settings: <perms> has"
7214 + " no name at " + parser.getPositionDescription());
7215 }
7216 } else {
7217 reportSettingsProblem(Log.WARN,
7218 "Unknown element under <perms>: "
7219 + parser.getName());
7220 }
7221 XmlUtils.skipCurrentTag(parser);
7222 }
7223 }
7224
7225 private void readPreferredPackagesLP(XmlPullParser parser)
7226 throws XmlPullParserException, IOException {
7227 int outerDepth = parser.getDepth();
7228 int type;
7229 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7230 && (type != XmlPullParser.END_TAG
7231 || parser.getDepth() > outerDepth)) {
7232 if (type == XmlPullParser.END_TAG
7233 || type == XmlPullParser.TEXT) {
7234 continue;
7235 }
7236
7237 String tagName = parser.getName();
7238 if (tagName.equals("item")) {
7239 String name = parser.getAttributeValue(null, "name");
7240 if (name != null) {
7241 mPendingPreferredPackages.add(name);
7242 } else {
7243 reportSettingsProblem(Log.WARN,
7244 "Error in package manager settings: <preferred-package> has no name at "
7245 + parser.getPositionDescription());
7246 }
7247 } else {
7248 reportSettingsProblem(Log.WARN,
7249 "Unknown element under <preferred-packages>: "
7250 + parser.getName());
7251 }
7252 XmlUtils.skipCurrentTag(parser);
7253 }
7254 }
7255
7256 private void readPreferredActivitiesLP(XmlPullParser parser)
7257 throws XmlPullParserException, IOException {
7258 int outerDepth = parser.getDepth();
7259 int type;
7260 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7261 && (type != XmlPullParser.END_TAG
7262 || parser.getDepth() > outerDepth)) {
7263 if (type == XmlPullParser.END_TAG
7264 || type == XmlPullParser.TEXT) {
7265 continue;
7266 }
7267
7268 String tagName = parser.getName();
7269 if (tagName.equals("item")) {
7270 PreferredActivity pa = new PreferredActivity(parser);
7271 if (pa.mParseError == null) {
7272 mPreferredActivities.addFilter(pa);
7273 } else {
7274 reportSettingsProblem(Log.WARN,
7275 "Error in package manager settings: <preferred-activity> "
7276 + pa.mParseError + " at "
7277 + parser.getPositionDescription());
7278 }
7279 } else {
7280 reportSettingsProblem(Log.WARN,
7281 "Unknown element under <preferred-activities>: "
7282 + parser.getName());
7283 XmlUtils.skipCurrentTag(parser);
7284 }
7285 }
7286 }
7287
7288 // Returns -1 if we could not find an available UserId to assign
7289 private int newUserIdLP(Object obj) {
7290 // Let's be stupidly inefficient for now...
7291 final int N = mUserIds.size();
7292 for (int i=0; i<N; i++) {
7293 if (mUserIds.get(i) == null) {
7294 mUserIds.set(i, obj);
7295 return FIRST_APPLICATION_UID + i;
7296 }
7297 }
7298
7299 // None left?
7300 if (N >= MAX_APPLICATION_UIDS) {
7301 return -1;
7302 }
7303
7304 mUserIds.add(obj);
7305 return FIRST_APPLICATION_UID + N;
7306 }
7307
7308 public PackageSetting getDisabledSystemPkg(String name) {
7309 synchronized(mPackages) {
7310 PackageSetting ps = mDisabledSysPackages.get(name);
7311 return ps;
7312 }
7313 }
7314
7315 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7316 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7317 if (Config.LOGV) {
7318 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7319 + " componentName = " + componentInfo.name);
7320 Log.v(TAG, "enabledComponents: "
7321 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7322 Log.v(TAG, "disabledComponents: "
7323 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7324 }
7325 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7326 || ((componentInfo.enabled
7327 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7328 || (componentInfo.applicationInfo.enabled
7329 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7330 && !packageSettings.disabledComponents.contains(componentInfo.name))
7331 || packageSettings.enabledComponents.contains(componentInfo.name));
7332 }
7333 }
7334}