blob: 5eb78c3dc6dad9dd5cdcc032954b0f1be74f9a89 [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;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700181 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182
183 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
184 // apps.
185 final File mDrmAppPrivateInstallDir;
186
187 // ----------------------------------------------------------------
188
189 // Lock for state used when installing and doing other long running
190 // operations. Methods that must be called with this lock held have
191 // the prefix "LI".
192 final Object mInstallLock = new Object();
193
194 // These are the directories in the 3rd party applications installed dir
195 // that we have currently loaded packages from. Keys are the application's
196 // installed zip file (absolute codePath), and values are Package.
197 final HashMap<String, PackageParser.Package> mAppDirs =
198 new HashMap<String, PackageParser.Package>();
199
200 // Information for the parser to write more useful error messages.
201 File mScanningPath;
202 int mLastScanError;
203
204 final int[] mOutPermissions = new int[3];
205
206 // ----------------------------------------------------------------
207
208 // Keys are String (package name), values are Package. This also serves
209 // as the lock for the global state. Methods that must be called with
210 // this lock held have the prefix "LP".
211 final HashMap<String, PackageParser.Package> mPackages =
212 new HashMap<String, PackageParser.Package>();
213
214 final Settings mSettings;
215 boolean mRestoredSettings;
216 boolean mReportedUidError;
217
218 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
219 int[] mGlobalGids;
220
221 // These are the built-in uid -> permission mappings that were read from the
222 // etc/permissions.xml file.
223 final SparseArray<HashSet<String>> mSystemPermissions =
224 new SparseArray<HashSet<String>>();
225
226 // These are the built-in shared libraries that were read from the
227 // etc/permissions.xml file.
228 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
229
Dianne Hackborn49237342009-08-27 20:08:01 -0700230 // Temporary for building the final shared libraries for an .apk.
231 String[] mTmpSharedLibraries = null;
232
233 // These are the features this devices supports that were read from the
234 // etc/permissions.xml file.
235 final HashMap<String, FeatureInfo> mAvailableFeatures =
236 new HashMap<String, FeatureInfo>();
237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 // All available activities, for your resolving pleasure.
239 final ActivityIntentResolver mActivities =
240 new ActivityIntentResolver();
241
242 // All available receivers, for your resolving pleasure.
243 final ActivityIntentResolver mReceivers =
244 new ActivityIntentResolver();
245
246 // All available services, for your resolving pleasure.
247 final ServiceIntentResolver mServices = new ServiceIntentResolver();
248
249 // Keys are String (provider class name), values are Provider.
250 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
251 new HashMap<ComponentName, PackageParser.Provider>();
252
253 // Mapping from provider base names (first directory in content URI codePath)
254 // to the provider information.
255 final HashMap<String, PackageParser.Provider> mProviders =
256 new HashMap<String, PackageParser.Provider>();
257
258 // Mapping from instrumentation class names to info about them.
259 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
260 new HashMap<ComponentName, PackageParser.Instrumentation>();
261
262 // Mapping from permission names to info about them.
263 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
264 new HashMap<String, PackageParser.PermissionGroup>();
265
Dianne Hackborn854060af2009-07-09 18:14:31 -0700266 // Broadcast actions that are only available to the system.
267 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 boolean mSystemReady;
270 boolean mSafeMode;
271 boolean mHasSystemUidErrors;
272
273 ApplicationInfo mAndroidApplication;
274 final ActivityInfo mResolveActivity = new ActivityInfo();
275 final ResolveInfo mResolveInfo = new ResolveInfo();
276 ComponentName mResolveComponentName;
277 PackageParser.Package mPlatformPackage;
278
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700279 // Set of pending broadcasts for aggregating enable/disable of components.
280 final HashMap<String, String> mPendingBroadcasts = new HashMap<String, String>();
281 static final int SEND_PENDING_BROADCAST = 1;
282 // Delay time in millisecs
283 static final int BROADCAST_DELAY = 10 * 1000;
284
285 class PackageHandler extends Handler {
286 PackageHandler(Looper looper) {
287 super(looper);
288 }
289 public void handleMessage(Message msg) {
290 switch (msg.what) {
291 case SEND_PENDING_BROADCAST : {
292 int size = 0;
293 String broadcastList[];
294 HashMap<String, String> tmpMap;
295 int uids[];
296 synchronized (mPackages) {
297 size = mPendingBroadcasts.size();
298 if (size <= 0) {
299 // Nothing to be done. Just return
300 return;
301 }
302 broadcastList = new String[size];
303 mPendingBroadcasts.keySet().toArray(broadcastList);
304 tmpMap = new HashMap<String, String>(mPendingBroadcasts);
305 uids = new int[size];
306 for (int i = 0; i < size; i++) {
307 PackageSetting ps = mSettings.mPackages.get(mPendingBroadcasts.get(broadcastList[i]));
308 uids[i] = (ps != null) ? ps.userId : -1;
309 }
310 mPendingBroadcasts.clear();
311 }
312 // Send broadcasts
313 for (int i = 0; i < size; i++) {
314 String className = broadcastList[i];
315 sendPackageChangedBroadcast(className, true, tmpMap.get(className), uids[i]);
316 }
317 break;
318 }
319 }
320 }
321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 public static final IPackageManager main(Context context, boolean factoryTest) {
323 PackageManagerService m = new PackageManagerService(context, factoryTest);
324 ServiceManager.addService("package", m);
325 return m;
326 }
327
328 static String[] splitString(String str, char sep) {
329 int count = 1;
330 int i = 0;
331 while ((i=str.indexOf(sep, i)) >= 0) {
332 count++;
333 i++;
334 }
335
336 String[] res = new String[count];
337 i=0;
338 count = 0;
339 int lastI=0;
340 while ((i=str.indexOf(sep, i)) >= 0) {
341 res[count] = str.substring(lastI, i);
342 count++;
343 i++;
344 lastI = i;
345 }
346 res[count] = str.substring(lastI, str.length());
347 return res;
348 }
349
350 public PackageManagerService(Context context, boolean factoryTest) {
351 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
352 SystemClock.uptimeMillis());
353
354 if (mSdkVersion <= 0) {
355 Log.w(TAG, "**** ro.build.version.sdk not set!");
356 }
357
358 mContext = context;
359 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700360 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 mMetrics = new DisplayMetrics();
362 mSettings = new Settings();
363 mSettings.addSharedUserLP("android.uid.system",
364 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
365 mSettings.addSharedUserLP("android.uid.phone",
366 MULTIPLE_APPLICATION_UIDS
367 ? RADIO_UID : FIRST_APPLICATION_UID,
368 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400369 mSettings.addSharedUserLP("android.uid.log",
370 MULTIPLE_APPLICATION_UIDS
371 ? LOG_UID : FIRST_APPLICATION_UID,
372 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373
374 String separateProcesses = SystemProperties.get("debug.separate_processes");
375 if (separateProcesses != null && separateProcesses.length() > 0) {
376 if ("*".equals(separateProcesses)) {
377 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
378 mSeparateProcesses = null;
379 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
380 } else {
381 mDefParseFlags = 0;
382 mSeparateProcesses = separateProcesses.split(",");
383 Log.w(TAG, "Running with debug.separate_processes: "
384 + separateProcesses);
385 }
386 } else {
387 mDefParseFlags = 0;
388 mSeparateProcesses = null;
389 }
390
391 Installer installer = new Installer();
392 // Little hacky thing to check if installd is here, to determine
393 // whether we are running on the simulator and thus need to take
394 // care of building the /data file structure ourself.
395 // (apparently the sim now has a working installer)
396 if (installer.ping() && Process.supportsProcesses()) {
397 mInstaller = installer;
398 } else {
399 mInstaller = null;
400 }
401
402 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
403 Display d = wm.getDefaultDisplay();
404 d.getMetrics(mMetrics);
405
406 synchronized (mInstallLock) {
407 synchronized (mPackages) {
408 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700409 mHandler = new PackageHandler(mHandlerThread.getLooper());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410
411 File dataDir = Environment.getDataDirectory();
412 mAppDataDir = new File(dataDir, "data");
413 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
414
415 if (mInstaller == null) {
416 // Make sure these dirs exist, when we are running in
417 // the simulator.
418 // Make a wide-open directory for random misc stuff.
419 File miscDir = new File(dataDir, "misc");
420 miscDir.mkdirs();
421 mAppDataDir.mkdirs();
422 mDrmAppPrivateInstallDir.mkdirs();
423 }
424
425 readPermissions();
426
427 mRestoredSettings = mSettings.readLP();
428 long startTime = SystemClock.uptimeMillis();
429
430 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
431 startTime);
432
433 int scanMode = SCAN_MONITOR;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700434 if (mNoDexOpt) {
435 Log.w(TAG, "Running ENG build: no pre-dexopt!");
436 scanMode |= SCAN_NO_DEX;
437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438
439 final HashSet<String> libFiles = new HashSet<String>();
440
441 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700442 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443
444 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700445 boolean didDexOpt = false;
446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 /**
448 * Out of paranoia, ensure that everything in the boot class
449 * path has been dexed.
450 */
451 String bootClassPath = System.getProperty("java.boot.class.path");
452 if (bootClassPath != null) {
453 String[] paths = splitString(bootClassPath, ':');
454 for (int i=0; i<paths.length; i++) {
455 try {
456 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
457 libFiles.add(paths[i]);
458 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700459 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 }
461 } catch (FileNotFoundException e) {
462 Log.w(TAG, "Boot class path not found: " + paths[i]);
463 } catch (IOException e) {
464 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
465 }
466 }
467 } else {
468 Log.w(TAG, "No BOOTCLASSPATH found!");
469 }
470
471 /**
472 * Also ensure all external libraries have had dexopt run on them.
473 */
474 if (mSharedLibraries.size() > 0) {
475 Iterator<String> libs = mSharedLibraries.values().iterator();
476 while (libs.hasNext()) {
477 String lib = libs.next();
478 try {
479 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
480 libFiles.add(lib);
481 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700482 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 }
484 } catch (FileNotFoundException e) {
485 Log.w(TAG, "Library not found: " + lib);
486 } catch (IOException e) {
487 Log.w(TAG, "Exception reading library: " + lib, e);
488 }
489 }
490 }
491
492 // Gross hack for now: we know this file doesn't contain any
493 // code, so don't dexopt it to avoid the resulting log spew.
494 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
495
496 /**
497 * And there are a number of commands implemented in Java, which
498 * we currently need to do the dexopt on so that they can be
499 * run from a non-root shell.
500 */
501 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700502 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 for (int i=0; i<frameworkFiles.length; i++) {
504 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
505 String path = libPath.getPath();
506 // Skip the file if we alrady did it.
507 if (libFiles.contains(path)) {
508 continue;
509 }
510 // Skip the file if it is not a type we want to dexopt.
511 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
512 continue;
513 }
514 try {
515 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
516 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700517 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 }
519 } catch (FileNotFoundException e) {
520 Log.w(TAG, "Jar not found: " + path);
521 } catch (IOException e) {
522 Log.w(TAG, "Exception reading jar: " + path, e);
523 }
524 }
525 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700526
527 if (didDexOpt) {
528 // If we had to do a dexopt of one of the previous
529 // things, then something on the system has changed.
530 // Consider this significant, and wipe away all other
531 // existing dexopt files to ensure we don't leave any
532 // dangling around.
533 String[] files = mDalvikCacheDir.list();
534 if (files != null) {
535 for (int i=0; i<files.length; i++) {
536 String fn = files[i];
537 if (fn.startsWith("data@app@")
538 || fn.startsWith("data@app-private@")) {
539 Log.i(TAG, "Pruning dalvik file: " + fn);
540 (new File(mDalvikCacheDir, fn)).delete();
541 }
542 }
543 }
544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 }
546
547 mFrameworkInstallObserver = new AppDirObserver(
548 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
549 mFrameworkInstallObserver.startWatching();
550 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
551 scanMode | SCAN_NO_DEX);
552 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
553 mSystemInstallObserver = new AppDirObserver(
554 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
555 mSystemInstallObserver.startWatching();
556 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
557 mAppInstallDir = new File(dataDir, "app");
558 if (mInstaller == null) {
559 // Make sure these dirs exist, when we are running in
560 // the simulator.
561 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
562 }
563 //look for any incomplete package installations
564 ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
565 //clean up list
566 for(int i = 0; i < deletePkgsList.size(); i++) {
567 //clean up here
568 cleanupInstallFailedPackage(deletePkgsList.get(i));
569 }
570 //delete tmp files
571 deleteTempPackageFiles();
572
573 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
574 SystemClock.uptimeMillis());
575 mAppInstallObserver = new AppDirObserver(
576 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
577 mAppInstallObserver.startWatching();
578 scanDirLI(mAppInstallDir, 0, scanMode);
579
580 mDrmAppInstallObserver = new AppDirObserver(
581 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
582 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -0700583 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584
585 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
586 SystemClock.uptimeMillis());
587 Log.i(TAG, "Time to scan packages: "
588 + ((SystemClock.uptimeMillis()-startTime)/1000f)
589 + " seconds");
590
591 updatePermissionsLP();
592
593 mSettings.writeLP();
594
595 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
596 SystemClock.uptimeMillis());
597
598 // Now after opening every single application zip, make sure they
599 // are all flushed. Not really needed, but keeps things nice and
600 // tidy.
601 Runtime.getRuntime().gc();
602 } // synchronized (mPackages)
603 } // synchronized (mInstallLock)
604 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 @Override
607 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
608 throws RemoteException {
609 try {
610 return super.onTransact(code, data, reply, flags);
611 } catch (RuntimeException e) {
612 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
613 Log.e(TAG, "Package Manager Crash", e);
614 }
615 throw e;
616 }
617 }
618
619 void cleanupInstallFailedPackage(String packageName) {
620 if (mInstaller != null) {
621 int retCode = mInstaller.remove(packageName);
622 if (retCode < 0) {
623 Log.w(TAG, "Couldn't remove app data directory for package: "
624 + packageName + ", retcode=" + retCode);
625 }
626 } else {
627 //for emulator
628 PackageParser.Package pkg = mPackages.get(packageName);
629 File dataDir = new File(pkg.applicationInfo.dataDir);
630 dataDir.delete();
631 }
632 mSettings.removePackageLP(packageName);
633 }
634
635 void readPermissions() {
636 // Read permissions from .../etc/permission directory.
637 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
638 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
639 Log.w(TAG, "No directory " + libraryDir + ", skipping");
640 return;
641 }
642 if (!libraryDir.canRead()) {
643 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
644 return;
645 }
646
647 // Iterate over the files in the directory and scan .xml files
648 for (File f : libraryDir.listFiles()) {
649 // We'll read platform.xml last
650 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
651 continue;
652 }
653
654 if (!f.getPath().endsWith(".xml")) {
655 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
656 continue;
657 }
658 if (!f.canRead()) {
659 Log.w(TAG, "Permissions library file " + f + " cannot be read");
660 continue;
661 }
662
663 readPermissionsFromXml(f);
664 }
665
666 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
667 final File permFile = new File(Environment.getRootDirectory(),
668 "etc/permissions/platform.xml");
669 readPermissionsFromXml(permFile);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700670
671 StringBuilder sb = new StringBuilder(128);
672 sb.append("Libs:");
673 Iterator<String> it = mSharedLibraries.keySet().iterator();
674 while (it.hasNext()) {
675 sb.append(' ');
676 String name = it.next();
677 sb.append(name);
678 sb.append(':');
679 sb.append(mSharedLibraries.get(name));
680 }
681 Log.i(TAG, sb.toString());
682
683 sb.setLength(0);
684 sb.append("Features:");
685 it = mAvailableFeatures.keySet().iterator();
686 while (it.hasNext()) {
687 sb.append(' ');
688 sb.append(it.next());
689 }
690 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 }
692
693 private void readPermissionsFromXml(File permFile) {
694 FileReader permReader = null;
695 try {
696 permReader = new FileReader(permFile);
697 } catch (FileNotFoundException e) {
698 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
699 return;
700 }
701
702 try {
703 XmlPullParser parser = Xml.newPullParser();
704 parser.setInput(permReader);
705
706 XmlUtils.beginDocument(parser, "permissions");
707
708 while (true) {
709 XmlUtils.nextElement(parser);
710 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
711 break;
712 }
713
714 String name = parser.getName();
715 if ("group".equals(name)) {
716 String gidStr = parser.getAttributeValue(null, "gid");
717 if (gidStr != null) {
718 int gid = Integer.parseInt(gidStr);
719 mGlobalGids = appendInt(mGlobalGids, gid);
720 } else {
721 Log.w(TAG, "<group> without gid at "
722 + parser.getPositionDescription());
723 }
724
725 XmlUtils.skipCurrentTag(parser);
726 continue;
727 } else if ("permission".equals(name)) {
728 String perm = parser.getAttributeValue(null, "name");
729 if (perm == null) {
730 Log.w(TAG, "<permission> without name at "
731 + parser.getPositionDescription());
732 XmlUtils.skipCurrentTag(parser);
733 continue;
734 }
735 perm = perm.intern();
736 readPermission(parser, perm);
737
738 } else if ("assign-permission".equals(name)) {
739 String perm = parser.getAttributeValue(null, "name");
740 if (perm == null) {
741 Log.w(TAG, "<assign-permission> without name at "
742 + parser.getPositionDescription());
743 XmlUtils.skipCurrentTag(parser);
744 continue;
745 }
746 String uidStr = parser.getAttributeValue(null, "uid");
747 if (uidStr == null) {
748 Log.w(TAG, "<assign-permission> without uid at "
749 + parser.getPositionDescription());
750 XmlUtils.skipCurrentTag(parser);
751 continue;
752 }
753 int uid = Process.getUidForName(uidStr);
754 if (uid < 0) {
755 Log.w(TAG, "<assign-permission> with unknown uid \""
756 + uidStr + "\" at "
757 + parser.getPositionDescription());
758 XmlUtils.skipCurrentTag(parser);
759 continue;
760 }
761 perm = perm.intern();
762 HashSet<String> perms = mSystemPermissions.get(uid);
763 if (perms == null) {
764 perms = new HashSet<String>();
765 mSystemPermissions.put(uid, perms);
766 }
767 perms.add(perm);
768 XmlUtils.skipCurrentTag(parser);
769
770 } else if ("library".equals(name)) {
771 String lname = parser.getAttributeValue(null, "name");
772 String lfile = parser.getAttributeValue(null, "file");
773 if (lname == null) {
774 Log.w(TAG, "<library> without name at "
775 + parser.getPositionDescription());
776 } else if (lfile == null) {
777 Log.w(TAG, "<library> without file at "
778 + parser.getPositionDescription());
779 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700780 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700781 mSharedLibraries.put(lname, lfile);
782 }
783 XmlUtils.skipCurrentTag(parser);
784 continue;
785
786 } else if ("feature".equals(name)) {
787 String fname = parser.getAttributeValue(null, "name");
788 if (fname == null) {
789 Log.w(TAG, "<feature> without name at "
790 + parser.getPositionDescription());
791 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700792 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700793 FeatureInfo fi = new FeatureInfo();
794 fi.name = fname;
795 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 }
797 XmlUtils.skipCurrentTag(parser);
798 continue;
799
800 } else {
801 XmlUtils.skipCurrentTag(parser);
802 continue;
803 }
804
805 }
806 } catch (XmlPullParserException e) {
807 Log.w(TAG, "Got execption parsing permissions.", e);
808 } catch (IOException e) {
809 Log.w(TAG, "Got execption parsing permissions.", e);
810 }
811 }
812
813 void readPermission(XmlPullParser parser, String name)
814 throws IOException, XmlPullParserException {
815
816 name = name.intern();
817
818 BasePermission bp = mSettings.mPermissions.get(name);
819 if (bp == null) {
820 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
821 mSettings.mPermissions.put(name, bp);
822 }
823 int outerDepth = parser.getDepth();
824 int type;
825 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
826 && (type != XmlPullParser.END_TAG
827 || parser.getDepth() > outerDepth)) {
828 if (type == XmlPullParser.END_TAG
829 || type == XmlPullParser.TEXT) {
830 continue;
831 }
832
833 String tagName = parser.getName();
834 if ("group".equals(tagName)) {
835 String gidStr = parser.getAttributeValue(null, "gid");
836 if (gidStr != null) {
837 int gid = Process.getGidForName(gidStr);
838 bp.gids = appendInt(bp.gids, gid);
839 } else {
840 Log.w(TAG, "<group> without gid at "
841 + parser.getPositionDescription());
842 }
843 }
844 XmlUtils.skipCurrentTag(parser);
845 }
846 }
847
848 static int[] appendInt(int[] cur, int val) {
849 if (cur == null) {
850 return new int[] { val };
851 }
852 final int N = cur.length;
853 for (int i=0; i<N; i++) {
854 if (cur[i] == val) {
855 return cur;
856 }
857 }
858 int[] ret = new int[N+1];
859 System.arraycopy(cur, 0, ret, 0, N);
860 ret[N] = val;
861 return ret;
862 }
863
864 static int[] appendInts(int[] cur, int[] add) {
865 if (add == null) return cur;
866 if (cur == null) return add;
867 final int N = add.length;
868 for (int i=0; i<N; i++) {
869 cur = appendInt(cur, add[i]);
870 }
871 return cur;
872 }
873
874 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
875 final PackageSetting ps = (PackageSetting)p.mExtras;
876 if (ps == null) {
877 return null;
878 }
879 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
880 return PackageParser.generatePackageInfo(p, gp.gids, flags);
881 }
882
883 public PackageInfo getPackageInfo(String packageName, int flags) {
884 synchronized (mPackages) {
885 PackageParser.Package p = mPackages.get(packageName);
886 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700887 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 + ": " + p);
889 if (p != null) {
890 return generatePackageInfo(p, flags);
891 }
892 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
893 return generatePackageInfoFromSettingsLP(packageName, flags);
894 }
895 }
896 return null;
897 }
898
899 public int getPackageUid(String packageName) {
900 synchronized (mPackages) {
901 PackageParser.Package p = mPackages.get(packageName);
902 if(p != null) {
903 return p.applicationInfo.uid;
904 }
905 PackageSetting ps = mSettings.mPackages.get(packageName);
906 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
907 return -1;
908 }
909 p = ps.pkg;
910 return p != null ? p.applicationInfo.uid : -1;
911 }
912 }
913
914 public int[] getPackageGids(String packageName) {
915 synchronized (mPackages) {
916 PackageParser.Package p = mPackages.get(packageName);
917 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700918 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 + ": " + p);
920 if (p != null) {
921 final PackageSetting ps = (PackageSetting)p.mExtras;
922 final SharedUserSetting suid = ps.sharedUser;
923 return suid != null ? suid.gids : ps.gids;
924 }
925 }
926 // stupid thing to indicate an error.
927 return new int[0];
928 }
929
930 public PermissionInfo getPermissionInfo(String name, int flags) {
931 synchronized (mPackages) {
932 final BasePermission p = mSettings.mPermissions.get(name);
933 if (p != null && p.perm != null) {
934 return PackageParser.generatePermissionInfo(p.perm, flags);
935 }
936 return null;
937 }
938 }
939
940 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
941 synchronized (mPackages) {
942 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
943 for (BasePermission p : mSettings.mPermissions.values()) {
944 if (group == null) {
945 if (p.perm.info.group == null) {
946 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
947 }
948 } else {
949 if (group.equals(p.perm.info.group)) {
950 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
951 }
952 }
953 }
954
955 if (out.size() > 0) {
956 return out;
957 }
958 return mPermissionGroups.containsKey(group) ? out : null;
959 }
960 }
961
962 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
963 synchronized (mPackages) {
964 return PackageParser.generatePermissionGroupInfo(
965 mPermissionGroups.get(name), flags);
966 }
967 }
968
969 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
970 synchronized (mPackages) {
971 final int N = mPermissionGroups.size();
972 ArrayList<PermissionGroupInfo> out
973 = new ArrayList<PermissionGroupInfo>(N);
974 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
975 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
976 }
977 return out;
978 }
979 }
980
981 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
982 PackageSetting ps = mSettings.mPackages.get(packageName);
983 if(ps != null) {
984 if(ps.pkg == null) {
985 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
986 if(pInfo != null) {
987 return pInfo.applicationInfo;
988 }
989 return null;
990 }
991 return PackageParser.generateApplicationInfo(ps.pkg, flags);
992 }
993 return null;
994 }
995
996 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
997 PackageSetting ps = mSettings.mPackages.get(packageName);
998 if(ps != null) {
999 if(ps.pkg == null) {
1000 ps.pkg = new PackageParser.Package(packageName);
1001 ps.pkg.applicationInfo.packageName = packageName;
1002 }
1003 return generatePackageInfo(ps.pkg, flags);
1004 }
1005 return null;
1006 }
1007
1008 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1009 synchronized (mPackages) {
1010 PackageParser.Package p = mPackages.get(packageName);
1011 if (Config.LOGV) Log.v(
1012 TAG, "getApplicationInfo " + packageName
1013 + ": " + p);
1014 if (p != null) {
1015 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001016 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 }
1018 if ("android".equals(packageName)||"system".equals(packageName)) {
1019 return mAndroidApplication;
1020 }
1021 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1022 return generateApplicationInfoFromSettingsLP(packageName, flags);
1023 }
1024 }
1025 return null;
1026 }
1027
1028
1029 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1030 mContext.enforceCallingOrSelfPermission(
1031 android.Manifest.permission.CLEAR_APP_CACHE, null);
1032 // Queue up an async operation since clearing cache may take a little while.
1033 mHandler.post(new Runnable() {
1034 public void run() {
1035 mHandler.removeCallbacks(this);
1036 int retCode = -1;
1037 if (mInstaller != null) {
1038 retCode = mInstaller.freeCache(freeStorageSize);
1039 if (retCode < 0) {
1040 Log.w(TAG, "Couldn't clear application caches");
1041 }
1042 } //end if mInstaller
1043 if (observer != null) {
1044 try {
1045 observer.onRemoveCompleted(null, (retCode >= 0));
1046 } catch (RemoteException e) {
1047 Log.w(TAG, "RemoveException when invoking call back");
1048 }
1049 }
1050 }
1051 });
1052 }
1053
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001054 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001055 mContext.enforceCallingOrSelfPermission(
1056 android.Manifest.permission.CLEAR_APP_CACHE, null);
1057 // Queue up an async operation since clearing cache may take a little while.
1058 mHandler.post(new Runnable() {
1059 public void run() {
1060 mHandler.removeCallbacks(this);
1061 int retCode = -1;
1062 if (mInstaller != null) {
1063 retCode = mInstaller.freeCache(freeStorageSize);
1064 if (retCode < 0) {
1065 Log.w(TAG, "Couldn't clear application caches");
1066 }
1067 }
1068 if(pi != null) {
1069 try {
1070 // Callback via pending intent
1071 int code = (retCode >= 0) ? 1 : 0;
1072 pi.sendIntent(null, code, null,
1073 null, null);
1074 } catch (SendIntentException e1) {
1075 Log.i(TAG, "Failed to send pending intent");
1076 }
1077 }
1078 }
1079 });
1080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081
1082 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1083 synchronized (mPackages) {
1084 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001085
1086 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001088 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 }
1090 if (mResolveComponentName.equals(component)) {
1091 return mResolveActivity;
1092 }
1093 }
1094 return null;
1095 }
1096
1097 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1098 synchronized (mPackages) {
1099 PackageParser.Activity a = mReceivers.mActivities.get(component);
1100 if (Config.LOGV) Log.v(
1101 TAG, "getReceiverInfo " + component + ": " + a);
1102 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1103 return PackageParser.generateActivityInfo(a, flags);
1104 }
1105 }
1106 return null;
1107 }
1108
1109 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1110 synchronized (mPackages) {
1111 PackageParser.Service s = mServices.mServices.get(component);
1112 if (Config.LOGV) Log.v(
1113 TAG, "getServiceInfo " + component + ": " + s);
1114 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1115 return PackageParser.generateServiceInfo(s, flags);
1116 }
1117 }
1118 return null;
1119 }
1120
1121 public String[] getSystemSharedLibraryNames() {
1122 Set<String> libSet;
1123 synchronized (mPackages) {
1124 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001125 int size = libSet.size();
1126 if (size > 0) {
1127 String[] libs = new String[size];
1128 libSet.toArray(libs);
1129 return libs;
1130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001132 return null;
1133 }
1134
1135 public FeatureInfo[] getSystemAvailableFeatures() {
1136 Collection<FeatureInfo> featSet;
1137 synchronized (mPackages) {
1138 featSet = mAvailableFeatures.values();
1139 int size = featSet.size();
1140 if (size > 0) {
1141 FeatureInfo[] features = new FeatureInfo[size+1];
1142 featSet.toArray(features);
1143 FeatureInfo fi = new FeatureInfo();
1144 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1145 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1146 features[size] = fi;
1147 return features;
1148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 }
1150 return null;
1151 }
1152
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001153 public boolean hasSystemFeature(String name) {
1154 synchronized (mPackages) {
1155 return mAvailableFeatures.containsKey(name);
1156 }
1157 }
1158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 public int checkPermission(String permName, String pkgName) {
1160 synchronized (mPackages) {
1161 PackageParser.Package p = mPackages.get(pkgName);
1162 if (p != null && p.mExtras != null) {
1163 PackageSetting ps = (PackageSetting)p.mExtras;
1164 if (ps.sharedUser != null) {
1165 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1166 return PackageManager.PERMISSION_GRANTED;
1167 }
1168 } else if (ps.grantedPermissions.contains(permName)) {
1169 return PackageManager.PERMISSION_GRANTED;
1170 }
1171 }
1172 }
1173 return PackageManager.PERMISSION_DENIED;
1174 }
1175
1176 public int checkUidPermission(String permName, int uid) {
1177 synchronized (mPackages) {
1178 Object obj = mSettings.getUserIdLP(uid);
1179 if (obj != null) {
1180 if (obj instanceof SharedUserSetting) {
1181 SharedUserSetting sus = (SharedUserSetting)obj;
1182 if (sus.grantedPermissions.contains(permName)) {
1183 return PackageManager.PERMISSION_GRANTED;
1184 }
1185 } else if (obj instanceof PackageSetting) {
1186 PackageSetting ps = (PackageSetting)obj;
1187 if (ps.grantedPermissions.contains(permName)) {
1188 return PackageManager.PERMISSION_GRANTED;
1189 }
1190 }
1191 } else {
1192 HashSet<String> perms = mSystemPermissions.get(uid);
1193 if (perms != null && perms.contains(permName)) {
1194 return PackageManager.PERMISSION_GRANTED;
1195 }
1196 }
1197 }
1198 return PackageManager.PERMISSION_DENIED;
1199 }
1200
1201 private BasePermission findPermissionTreeLP(String permName) {
1202 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1203 if (permName.startsWith(bp.name) &&
1204 permName.length() > bp.name.length() &&
1205 permName.charAt(bp.name.length()) == '.') {
1206 return bp;
1207 }
1208 }
1209 return null;
1210 }
1211
1212 private BasePermission checkPermissionTreeLP(String permName) {
1213 if (permName != null) {
1214 BasePermission bp = findPermissionTreeLP(permName);
1215 if (bp != null) {
1216 if (bp.uid == Binder.getCallingUid()) {
1217 return bp;
1218 }
1219 throw new SecurityException("Calling uid "
1220 + Binder.getCallingUid()
1221 + " is not allowed to add to permission tree "
1222 + bp.name + " owned by uid " + bp.uid);
1223 }
1224 }
1225 throw new SecurityException("No permission tree found for " + permName);
1226 }
1227
1228 public boolean addPermission(PermissionInfo info) {
1229 synchronized (mPackages) {
1230 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1231 throw new SecurityException("Label must be specified in permission");
1232 }
1233 BasePermission tree = checkPermissionTreeLP(info.name);
1234 BasePermission bp = mSettings.mPermissions.get(info.name);
1235 boolean added = bp == null;
1236 if (added) {
1237 bp = new BasePermission(info.name, tree.sourcePackage,
1238 BasePermission.TYPE_DYNAMIC);
1239 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1240 throw new SecurityException(
1241 "Not allowed to modify non-dynamic permission "
1242 + info.name);
1243 }
1244 bp.perm = new PackageParser.Permission(tree.perm.owner,
1245 new PermissionInfo(info));
1246 bp.perm.info.packageName = tree.perm.info.packageName;
1247 bp.uid = tree.uid;
1248 if (added) {
1249 mSettings.mPermissions.put(info.name, bp);
1250 }
1251 mSettings.writeLP();
1252 return added;
1253 }
1254 }
1255
1256 public void removePermission(String name) {
1257 synchronized (mPackages) {
1258 checkPermissionTreeLP(name);
1259 BasePermission bp = mSettings.mPermissions.get(name);
1260 if (bp != null) {
1261 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1262 throw new SecurityException(
1263 "Not allowed to modify non-dynamic permission "
1264 + name);
1265 }
1266 mSettings.mPermissions.remove(name);
1267 mSettings.writeLP();
1268 }
1269 }
1270 }
1271
Dianne Hackborn854060af2009-07-09 18:14:31 -07001272 public boolean isProtectedBroadcast(String actionName) {
1273 synchronized (mPackages) {
1274 return mProtectedBroadcasts.contains(actionName);
1275 }
1276 }
1277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 public int checkSignatures(String pkg1, String pkg2) {
1279 synchronized (mPackages) {
1280 PackageParser.Package p1 = mPackages.get(pkg1);
1281 PackageParser.Package p2 = mPackages.get(pkg2);
1282 if (p1 == null || p1.mExtras == null
1283 || p2 == null || p2.mExtras == null) {
1284 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1285 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001286 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 }
1288 }
1289
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001290 public int checkUidSignatures(int uid1, int uid2) {
1291 synchronized (mPackages) {
1292 Signature[] s1;
1293 Signature[] s2;
1294 Object obj = mSettings.getUserIdLP(uid1);
1295 if (obj != null) {
1296 if (obj instanceof SharedUserSetting) {
1297 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1298 } else if (obj instanceof PackageSetting) {
1299 s1 = ((PackageSetting)obj).signatures.mSignatures;
1300 } else {
1301 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1302 }
1303 } else {
1304 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1305 }
1306 obj = mSettings.getUserIdLP(uid2);
1307 if (obj != null) {
1308 if (obj instanceof SharedUserSetting) {
1309 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1310 } else if (obj instanceof PackageSetting) {
1311 s2 = ((PackageSetting)obj).signatures.mSignatures;
1312 } else {
1313 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1314 }
1315 } else {
1316 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1317 }
1318 return checkSignaturesLP(s1, s2);
1319 }
1320 }
1321
1322 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1323 if (s1 == null) {
1324 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1326 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1327 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001328 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1330 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001331 final int N1 = s1.length;
1332 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 for (int i=0; i<N1; i++) {
1334 boolean match = false;
1335 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001336 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 match = true;
1338 break;
1339 }
1340 }
1341 if (!match) {
1342 return PackageManager.SIGNATURE_NO_MATCH;
1343 }
1344 }
1345 return PackageManager.SIGNATURE_MATCH;
1346 }
1347
1348 public String[] getPackagesForUid(int uid) {
1349 synchronized (mPackages) {
1350 Object obj = mSettings.getUserIdLP(uid);
1351 if (obj instanceof SharedUserSetting) {
1352 SharedUserSetting sus = (SharedUserSetting)obj;
1353 final int N = sus.packages.size();
1354 String[] res = new String[N];
1355 Iterator<PackageSetting> it = sus.packages.iterator();
1356 int i=0;
1357 while (it.hasNext()) {
1358 res[i++] = it.next().name;
1359 }
1360 return res;
1361 } else if (obj instanceof PackageSetting) {
1362 PackageSetting ps = (PackageSetting)obj;
1363 return new String[] { ps.name };
1364 }
1365 }
1366 return null;
1367 }
1368
1369 public String getNameForUid(int uid) {
1370 synchronized (mPackages) {
1371 Object obj = mSettings.getUserIdLP(uid);
1372 if (obj instanceof SharedUserSetting) {
1373 SharedUserSetting sus = (SharedUserSetting)obj;
1374 return sus.name + ":" + sus.userId;
1375 } else if (obj instanceof PackageSetting) {
1376 PackageSetting ps = (PackageSetting)obj;
1377 return ps.name;
1378 }
1379 }
1380 return null;
1381 }
1382
1383 public int getUidForSharedUser(String sharedUserName) {
1384 if(sharedUserName == null) {
1385 return -1;
1386 }
1387 synchronized (mPackages) {
1388 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1389 if(suid == null) {
1390 return -1;
1391 }
1392 return suid.userId;
1393 }
1394 }
1395
1396 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1397 int flags) {
1398 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001399 return chooseBestActivity(intent, resolvedType, flags, query);
1400 }
1401
Mihai Predaeae850c2009-05-13 10:13:48 +02001402 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1403 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 if (query != null) {
1405 final int N = query.size();
1406 if (N == 1) {
1407 return query.get(0);
1408 } else if (N > 1) {
1409 // If there is more than one activity with the same priority,
1410 // then let the user decide between them.
1411 ResolveInfo r0 = query.get(0);
1412 ResolveInfo r1 = query.get(1);
1413 if (false) {
1414 System.out.println(r0.activityInfo.name +
1415 "=" + r0.priority + " vs " +
1416 r1.activityInfo.name +
1417 "=" + r1.priority);
1418 }
1419 // If the first activity has a higher priority, or a different
1420 // default, then it is always desireable to pick it.
1421 if (r0.priority != r1.priority
1422 || r0.preferredOrder != r1.preferredOrder
1423 || r0.isDefault != r1.isDefault) {
1424 return query.get(0);
1425 }
1426 // If we have saved a preference for a preferred activity for
1427 // this Intent, use that.
1428 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1429 flags, query, r0.priority);
1430 if (ri != null) {
1431 return ri;
1432 }
1433 return mResolveInfo;
1434 }
1435 }
1436 return null;
1437 }
1438
1439 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1440 int flags, List<ResolveInfo> query, int priority) {
1441 synchronized (mPackages) {
1442 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1443 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001444 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1446 if (prefs != null && prefs.size() > 0) {
1447 // First figure out how good the original match set is.
1448 // We will only allow preferred activities that came
1449 // from the same match quality.
1450 int match = 0;
1451 final int N = query.size();
1452 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1453 for (int j=0; j<N; j++) {
1454 ResolveInfo ri = query.get(j);
1455 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1456 + ": 0x" + Integer.toHexString(match));
1457 if (ri.match > match) match = ri.match;
1458 }
1459 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1460 + Integer.toHexString(match));
1461 match &= IntentFilter.MATCH_CATEGORY_MASK;
1462 final int M = prefs.size();
1463 for (int i=0; i<M; i++) {
1464 PreferredActivity pa = prefs.get(i);
1465 if (pa.mMatch != match) {
1466 continue;
1467 }
1468 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1469 if (DEBUG_PREFERRED) {
1470 Log.v(TAG, "Got preferred activity:");
1471 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1472 }
1473 if (ai != null) {
1474 for (int j=0; j<N; j++) {
1475 ResolveInfo ri = query.get(j);
1476 if (!ri.activityInfo.applicationInfo.packageName
1477 .equals(ai.applicationInfo.packageName)) {
1478 continue;
1479 }
1480 if (!ri.activityInfo.name.equals(ai.name)) {
1481 continue;
1482 }
1483
1484 // Okay we found a previously set preferred app.
1485 // If the result set is different from when this
1486 // was created, we need to clear it and re-ask the
1487 // user their preference.
1488 if (!pa.sameSet(query, priority)) {
1489 Log.i(TAG, "Result set changed, dropping preferred activity for "
1490 + intent + " type " + resolvedType);
1491 mSettings.mPreferredActivities.removeFilter(pa);
1492 return null;
1493 }
1494
1495 // Yay!
1496 return ri;
1497 }
1498 }
1499 }
1500 }
1501 }
1502 return null;
1503 }
1504
1505 public List<ResolveInfo> queryIntentActivities(Intent intent,
1506 String resolvedType, int flags) {
1507 ComponentName comp = intent.getComponent();
1508 if (comp != null) {
1509 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1510 ActivityInfo ai = getActivityInfo(comp, flags);
1511 if (ai != null) {
1512 ResolveInfo ri = new ResolveInfo();
1513 ri.activityInfo = ai;
1514 list.add(ri);
1515 }
1516 return list;
1517 }
1518
1519 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001520 String pkgName = intent.getPackage();
1521 if (pkgName == null) {
1522 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1523 resolvedType, flags);
1524 }
1525 PackageParser.Package pkg = mPackages.get(pkgName);
1526 if (pkg != null) {
1527 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1528 resolvedType, flags, pkg.activities);
1529 }
1530 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 }
1533
1534 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1535 Intent[] specifics, String[] specificTypes, Intent intent,
1536 String resolvedType, int flags) {
1537 final String resultsAction = intent.getAction();
1538
1539 List<ResolveInfo> results = queryIntentActivities(
1540 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1541 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1542
1543 int specificsPos = 0;
1544 int N;
1545
1546 // todo: note that the algorithm used here is O(N^2). This
1547 // isn't a problem in our current environment, but if we start running
1548 // into situations where we have more than 5 or 10 matches then this
1549 // should probably be changed to something smarter...
1550
1551 // First we go through and resolve each of the specific items
1552 // that were supplied, taking care of removing any corresponding
1553 // duplicate items in the generic resolve list.
1554 if (specifics != null) {
1555 for (int i=0; i<specifics.length; i++) {
1556 final Intent sintent = specifics[i];
1557 if (sintent == null) {
1558 continue;
1559 }
1560
1561 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1562 String action = sintent.getAction();
1563 if (resultsAction != null && resultsAction.equals(action)) {
1564 // If this action was explicitly requested, then don't
1565 // remove things that have it.
1566 action = null;
1567 }
1568 ComponentName comp = sintent.getComponent();
1569 ResolveInfo ri = null;
1570 ActivityInfo ai = null;
1571 if (comp == null) {
1572 ri = resolveIntent(
1573 sintent,
1574 specificTypes != null ? specificTypes[i] : null,
1575 flags);
1576 if (ri == null) {
1577 continue;
1578 }
1579 if (ri == mResolveInfo) {
1580 // ACK! Must do something better with this.
1581 }
1582 ai = ri.activityInfo;
1583 comp = new ComponentName(ai.applicationInfo.packageName,
1584 ai.name);
1585 } else {
1586 ai = getActivityInfo(comp, flags);
1587 if (ai == null) {
1588 continue;
1589 }
1590 }
1591
1592 // Look for any generic query activities that are duplicates
1593 // of this specific one, and remove them from the results.
1594 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1595 N = results.size();
1596 int j;
1597 for (j=specificsPos; j<N; j++) {
1598 ResolveInfo sri = results.get(j);
1599 if ((sri.activityInfo.name.equals(comp.getClassName())
1600 && sri.activityInfo.applicationInfo.packageName.equals(
1601 comp.getPackageName()))
1602 || (action != null && sri.filter.matchAction(action))) {
1603 results.remove(j);
1604 if (Config.LOGV) Log.v(
1605 TAG, "Removing duplicate item from " + j
1606 + " due to specific " + specificsPos);
1607 if (ri == null) {
1608 ri = sri;
1609 }
1610 j--;
1611 N--;
1612 }
1613 }
1614
1615 // Add this specific item to its proper place.
1616 if (ri == null) {
1617 ri = new ResolveInfo();
1618 ri.activityInfo = ai;
1619 }
1620 results.add(specificsPos, ri);
1621 ri.specificIndex = i;
1622 specificsPos++;
1623 }
1624 }
1625
1626 // Now we go through the remaining generic results and remove any
1627 // duplicate actions that are found here.
1628 N = results.size();
1629 for (int i=specificsPos; i<N-1; i++) {
1630 final ResolveInfo rii = results.get(i);
1631 if (rii.filter == null) {
1632 continue;
1633 }
1634
1635 // Iterate over all of the actions of this result's intent
1636 // filter... typically this should be just one.
1637 final Iterator<String> it = rii.filter.actionsIterator();
1638 if (it == null) {
1639 continue;
1640 }
1641 while (it.hasNext()) {
1642 final String action = it.next();
1643 if (resultsAction != null && resultsAction.equals(action)) {
1644 // If this action was explicitly requested, then don't
1645 // remove things that have it.
1646 continue;
1647 }
1648 for (int j=i+1; j<N; j++) {
1649 final ResolveInfo rij = results.get(j);
1650 if (rij.filter != null && rij.filter.hasAction(action)) {
1651 results.remove(j);
1652 if (Config.LOGV) Log.v(
1653 TAG, "Removing duplicate item from " + j
1654 + " due to action " + action + " at " + i);
1655 j--;
1656 N--;
1657 }
1658 }
1659 }
1660
1661 // If the caller didn't request filter information, drop it now
1662 // so we don't have to marshall/unmarshall it.
1663 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1664 rii.filter = null;
1665 }
1666 }
1667
1668 // Filter out the caller activity if so requested.
1669 if (caller != null) {
1670 N = results.size();
1671 for (int i=0; i<N; i++) {
1672 ActivityInfo ainfo = results.get(i).activityInfo;
1673 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1674 && caller.getClassName().equals(ainfo.name)) {
1675 results.remove(i);
1676 break;
1677 }
1678 }
1679 }
1680
1681 // If the caller didn't request filter information,
1682 // drop them now so we don't have to
1683 // marshall/unmarshall it.
1684 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1685 N = results.size();
1686 for (int i=0; i<N; i++) {
1687 results.get(i).filter = null;
1688 }
1689 }
1690
1691 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1692 return results;
1693 }
1694
1695 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1696 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001697 ComponentName comp = intent.getComponent();
1698 if (comp != null) {
1699 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1700 ActivityInfo ai = getReceiverInfo(comp, flags);
1701 if (ai != null) {
1702 ResolveInfo ri = new ResolveInfo();
1703 ri.activityInfo = ai;
1704 list.add(ri);
1705 }
1706 return list;
1707 }
1708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001710 String pkgName = intent.getPackage();
1711 if (pkgName == null) {
1712 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1713 resolvedType, flags);
1714 }
1715 PackageParser.Package pkg = mPackages.get(pkgName);
1716 if (pkg != null) {
1717 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1718 resolvedType, flags, pkg.receivers);
1719 }
1720 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 }
1722 }
1723
1724 public ResolveInfo resolveService(Intent intent, String resolvedType,
1725 int flags) {
1726 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1727 flags);
1728 if (query != null) {
1729 if (query.size() >= 1) {
1730 // If there is more than one service with the same priority,
1731 // just arbitrarily pick the first one.
1732 return query.get(0);
1733 }
1734 }
1735 return null;
1736 }
1737
1738 public List<ResolveInfo> queryIntentServices(Intent intent,
1739 String resolvedType, int flags) {
1740 ComponentName comp = intent.getComponent();
1741 if (comp != null) {
1742 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1743 ServiceInfo si = getServiceInfo(comp, flags);
1744 if (si != null) {
1745 ResolveInfo ri = new ResolveInfo();
1746 ri.serviceInfo = si;
1747 list.add(ri);
1748 }
1749 return list;
1750 }
1751
1752 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001753 String pkgName = intent.getPackage();
1754 if (pkgName == null) {
1755 return (List<ResolveInfo>)mServices.queryIntent(intent,
1756 resolvedType, flags);
1757 }
1758 PackageParser.Package pkg = mPackages.get(pkgName);
1759 if (pkg != null) {
1760 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1761 resolvedType, flags, pkg.services);
1762 }
1763 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 }
1765 }
1766
1767 public List<PackageInfo> getInstalledPackages(int flags) {
1768 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1769
1770 synchronized (mPackages) {
1771 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1772 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1773 while (i.hasNext()) {
1774 final PackageSetting ps = i.next();
1775 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1776 if(psPkg != null) {
1777 finalList.add(psPkg);
1778 }
1779 }
1780 }
1781 else {
1782 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1783 while (i.hasNext()) {
1784 final PackageParser.Package p = i.next();
1785 if (p.applicationInfo != null) {
1786 PackageInfo pi = generatePackageInfo(p, flags);
1787 if(pi != null) {
1788 finalList.add(pi);
1789 }
1790 }
1791 }
1792 }
1793 }
1794 return finalList;
1795 }
1796
1797 public List<ApplicationInfo> getInstalledApplications(int flags) {
1798 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1799 synchronized(mPackages) {
1800 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1801 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1802 while (i.hasNext()) {
1803 final PackageSetting ps = i.next();
1804 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1805 if(ai != null) {
1806 finalList.add(ai);
1807 }
1808 }
1809 }
1810 else {
1811 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1812 while (i.hasNext()) {
1813 final PackageParser.Package p = i.next();
1814 if (p.applicationInfo != null) {
1815 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1816 if(ai != null) {
1817 finalList.add(ai);
1818 }
1819 }
1820 }
1821 }
1822 }
1823 return finalList;
1824 }
1825
1826 public List<ApplicationInfo> getPersistentApplications(int flags) {
1827 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1828
1829 synchronized (mPackages) {
1830 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1831 while (i.hasNext()) {
1832 PackageParser.Package p = i.next();
1833 if (p.applicationInfo != null
1834 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1835 && (!mSafeMode || (p.applicationInfo.flags
1836 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1837 finalList.add(p.applicationInfo);
1838 }
1839 }
1840 }
1841
1842 return finalList;
1843 }
1844
1845 public ProviderInfo resolveContentProvider(String name, int flags) {
1846 synchronized (mPackages) {
1847 final PackageParser.Provider provider = mProviders.get(name);
1848 return provider != null
1849 && mSettings.isEnabledLP(provider.info, flags)
1850 && (!mSafeMode || (provider.info.applicationInfo.flags
1851 &ApplicationInfo.FLAG_SYSTEM) != 0)
1852 ? PackageParser.generateProviderInfo(provider, flags)
1853 : null;
1854 }
1855 }
1856
Fred Quintana718d8a22009-04-29 17:53:20 -07001857 /**
1858 * @deprecated
1859 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 public void querySyncProviders(List outNames, List outInfo) {
1861 synchronized (mPackages) {
1862 Iterator<Map.Entry<String, PackageParser.Provider>> i
1863 = mProviders.entrySet().iterator();
1864
1865 while (i.hasNext()) {
1866 Map.Entry<String, PackageParser.Provider> entry = i.next();
1867 PackageParser.Provider p = entry.getValue();
1868
1869 if (p.syncable
1870 && (!mSafeMode || (p.info.applicationInfo.flags
1871 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1872 outNames.add(entry.getKey());
1873 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1874 }
1875 }
1876 }
1877 }
1878
1879 public List<ProviderInfo> queryContentProviders(String processName,
1880 int uid, int flags) {
1881 ArrayList<ProviderInfo> finalList = null;
1882
1883 synchronized (mPackages) {
1884 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1885 while (i.hasNext()) {
1886 PackageParser.Provider p = i.next();
1887 if (p.info.authority != null
1888 && (processName == null ||
1889 (p.info.processName.equals(processName)
1890 && p.info.applicationInfo.uid == uid))
1891 && mSettings.isEnabledLP(p.info, flags)
1892 && (!mSafeMode || (p.info.applicationInfo.flags
1893 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1894 if (finalList == null) {
1895 finalList = new ArrayList<ProviderInfo>(3);
1896 }
1897 finalList.add(PackageParser.generateProviderInfo(p,
1898 flags));
1899 }
1900 }
1901 }
1902
1903 if (finalList != null) {
1904 Collections.sort(finalList, mProviderInitOrderSorter);
1905 }
1906
1907 return finalList;
1908 }
1909
1910 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1911 int flags) {
1912 synchronized (mPackages) {
1913 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1914 return PackageParser.generateInstrumentationInfo(i, flags);
1915 }
1916 }
1917
1918 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1919 int flags) {
1920 ArrayList<InstrumentationInfo> finalList =
1921 new ArrayList<InstrumentationInfo>();
1922
1923 synchronized (mPackages) {
1924 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1925 while (i.hasNext()) {
1926 PackageParser.Instrumentation p = i.next();
1927 if (targetPackage == null
1928 || targetPackage.equals(p.info.targetPackage)) {
1929 finalList.add(PackageParser.generateInstrumentationInfo(p,
1930 flags));
1931 }
1932 }
1933 }
1934
1935 return finalList;
1936 }
1937
1938 private void scanDirLI(File dir, int flags, int scanMode) {
1939 Log.d(TAG, "Scanning app dir " + dir);
1940
1941 String[] files = dir.list();
1942
1943 int i;
1944 for (i=0; i<files.length; i++) {
1945 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001946 File resFile = file;
1947 // Pick up the resource path from settings for fwd locked apps
1948 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1949 resFile = null;
1950 }
1951 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1953 }
1954 }
1955
1956 private static void reportSettingsProblem(int priority, String msg) {
1957 try {
1958 File dataDir = Environment.getDataDirectory();
1959 File systemDir = new File(dataDir, "system");
1960 File fname = new File(systemDir, "uiderrors.txt");
1961 FileOutputStream out = new FileOutputStream(fname, true);
1962 PrintWriter pw = new PrintWriter(out);
1963 pw.println(msg);
1964 pw.close();
1965 FileUtils.setPermissions(
1966 fname.toString(),
1967 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1968 -1, -1);
1969 } catch (java.io.IOException e) {
1970 }
1971 Log.println(priority, TAG, msg);
1972 }
1973
1974 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1975 PackageParser.Package pkg, File srcFile, int parseFlags) {
1976 if (GET_CERTIFICATES) {
1977 if (ps == null || !ps.codePath.equals(srcFile)
1978 || ps.getTimeStamp() != srcFile.lastModified()) {
1979 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1980 if (!pp.collectCertificates(pkg, parseFlags)) {
1981 mLastScanError = pp.getParseError();
1982 return false;
1983 }
1984 }
1985 }
1986 return true;
1987 }
1988
1989 /*
1990 * Scan a package and return the newly parsed package.
1991 * Returns null in case of errors and the error code is stored in mLastScanError
1992 */
1993 private PackageParser.Package scanPackageLI(File scanFile,
1994 File destCodeFile, File destResourceFile, int parseFlags,
1995 int scanMode) {
1996 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1997 parseFlags |= mDefParseFlags;
1998 PackageParser pp = new PackageParser(scanFile.getPath());
1999 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07002000 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 final PackageParser.Package pkg = pp.parsePackage(scanFile,
2002 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
2003 if (pkg == null) {
2004 mLastScanError = pp.getParseError();
2005 return null;
2006 }
2007 PackageSetting ps;
2008 PackageSetting updatedPkg;
2009 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002010 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2012 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002013 // Verify certificates first
2014 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2015 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2016 return null;
2017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 if (updatedPkg != null) {
2019 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2020 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2021 }
2022 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2023 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002024 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2025 if (pkg.mVersionCode < ps.versionCode) {
2026 // The system package has been updated and the code path does not match
2027 // Ignore entry. Just return
2028 Log.w(TAG, "Package:" + pkg.packageName +
2029 " has been updated. Ignoring the one from path:"+scanFile);
2030 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2031 return null;
2032 } else {
2033 // Delete the older apk pointed to by ps
2034 // At this point, its safely assumed that package installation for
2035 // apps in system partition will go through. If not there won't be a working
2036 // version of the app
2037 synchronized (mPackages) {
2038 // Just remove the loaded entries from package lists.
2039 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002040 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002041 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2042 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 }
2045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 // The apk is forward locked (not public) if its code and resources
2047 // are kept in different files.
2048 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2049 scanMode |= SCAN_FORWARD_LOCKED;
2050 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002051 File resFile = destResourceFile;
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002052 if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002053 resFile = getFwdLockedResource(ps.name);
2054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002056 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2058 }
2059
2060 private static String fixProcessName(String defProcessName,
2061 String processName, int uid) {
2062 if (processName == null) {
2063 return defProcessName;
2064 }
2065 return processName;
2066 }
2067
2068 private boolean verifySignaturesLP(PackageSetting pkgSetting,
2069 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2070 if (pkg.mSignatures != null) {
2071 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2072 updateSignature)) {
2073 Log.e(TAG, "Package " + pkg.packageName
2074 + " signatures do not match the previously installed version; ignoring!");
2075 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2076 return false;
2077 }
2078
2079 if (pkgSetting.sharedUser != null) {
2080 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2081 pkg.mSignatures, updateSignature)) {
2082 Log.e(TAG, "Package " + pkg.packageName
2083 + " has no signatures that match those in shared user "
2084 + pkgSetting.sharedUser.name + "; ignoring!");
2085 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2086 return false;
2087 }
2088 }
2089 } else {
2090 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2091 }
2092 return true;
2093 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002094
2095 public boolean performDexOpt(String packageName) {
2096 if (!mNoDexOpt) {
2097 return false;
2098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002100 PackageParser.Package p;
2101 synchronized (mPackages) {
2102 p = mPackages.get(packageName);
2103 if (p == null || p.mDidDexOpt) {
2104 return false;
2105 }
2106 }
2107 synchronized (mInstallLock) {
2108 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2109 }
2110 }
2111
2112 static final int DEX_OPT_SKIPPED = 0;
2113 static final int DEX_OPT_PERFORMED = 1;
2114 static final int DEX_OPT_FAILED = -1;
2115
2116 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2117 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002118 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002119 String path = pkg.mScanPath;
2120 int ret = 0;
2121 try {
2122 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2123 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2124 !pkg.mForwardLocked);
2125 pkg.mDidDexOpt = true;
2126 performed = true;
2127 }
2128 } catch (FileNotFoundException e) {
2129 Log.w(TAG, "Apk not found for dexopt: " + path);
2130 ret = -1;
2131 } catch (IOException e) {
2132 Log.w(TAG, "Exception reading apk: " + path, e);
2133 ret = -1;
2134 }
2135 if (ret < 0) {
2136 //error from installer
2137 return DEX_OPT_FAILED;
2138 }
2139 }
2140
2141 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2142 }
2143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 private PackageParser.Package scanPackageLI(
2145 File scanFile, File destCodeFile, File destResourceFile,
2146 PackageParser.Package pkg, int parseFlags, int scanMode) {
2147
2148 mScanningPath = scanFile;
2149 if (pkg == null) {
2150 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2151 return null;
2152 }
2153
2154 final String pkgName = pkg.applicationInfo.packageName;
2155 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2156 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2157 }
2158
2159 if (pkgName.equals("android")) {
2160 synchronized (mPackages) {
2161 if (mAndroidApplication != null) {
2162 Log.w(TAG, "*************************************************");
2163 Log.w(TAG, "Core android package being redefined. Skipping.");
2164 Log.w(TAG, " file=" + mScanningPath);
2165 Log.w(TAG, "*************************************************");
2166 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2167 return null;
2168 }
2169
2170 // Set up information for our fall-back user intent resolution
2171 // activity.
2172 mPlatformPackage = pkg;
2173 pkg.mVersionCode = mSdkVersion;
2174 mAndroidApplication = pkg.applicationInfo;
2175 mResolveActivity.applicationInfo = mAndroidApplication;
2176 mResolveActivity.name = ResolverActivity.class.getName();
2177 mResolveActivity.packageName = mAndroidApplication.packageName;
2178 mResolveActivity.processName = mAndroidApplication.processName;
2179 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2180 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2181 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2182 mResolveActivity.exported = true;
2183 mResolveActivity.enabled = true;
2184 mResolveInfo.activityInfo = mResolveActivity;
2185 mResolveInfo.priority = 0;
2186 mResolveInfo.preferredOrder = 0;
2187 mResolveInfo.match = 0;
2188 mResolveComponentName = new ComponentName(
2189 mAndroidApplication.packageName, mResolveActivity.name);
2190 }
2191 }
2192
2193 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2194 TAG, "Scanning package " + pkgName);
2195 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2196 Log.w(TAG, "*************************************************");
2197 Log.w(TAG, "Application package " + pkgName
2198 + " already installed. Skipping duplicate.");
2199 Log.w(TAG, "*************************************************");
2200 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2201 return null;
2202 }
2203
2204 SharedUserSetting suid = null;
2205 PackageSetting pkgSetting = null;
2206
2207 boolean removeExisting = false;
2208
2209 synchronized (mPackages) {
2210 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002211 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2212 if (mTmpSharedLibraries == null ||
2213 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2214 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2215 }
2216 int num = 0;
2217 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2218 for (int i=0; i<N; i++) {
2219 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 if (file == null) {
2221 Log.e(TAG, "Package " + pkg.packageName
2222 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002223 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2225 return null;
2226 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002227 mTmpSharedLibraries[num] = file;
2228 num++;
2229 }
2230 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2231 for (int i=0; i<N; i++) {
2232 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2233 if (file == null) {
2234 Log.w(TAG, "Package " + pkg.packageName
2235 + " desires unavailable shared library "
2236 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2237 } else {
2238 mTmpSharedLibraries[num] = file;
2239 num++;
2240 }
2241 }
2242 if (num > 0) {
2243 pkg.usesLibraryFiles = new String[num];
2244 System.arraycopy(mTmpSharedLibraries, 0,
2245 pkg.usesLibraryFiles, 0, num);
2246 }
2247
2248 if (pkg.reqFeatures != null) {
2249 N = pkg.reqFeatures.size();
2250 for (int i=0; i<N; i++) {
2251 FeatureInfo fi = pkg.reqFeatures.get(i);
2252 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2253 // Don't care.
2254 continue;
2255 }
2256
2257 if (fi.name != null) {
2258 if (mAvailableFeatures.get(fi.name) == null) {
2259 Log.e(TAG, "Package " + pkg.packageName
2260 + " requires unavailable feature "
2261 + fi.name + "; failing!");
2262 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2263 return null;
2264 }
2265 }
2266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 }
2268 }
2269
2270 if (pkg.mSharedUserId != null) {
2271 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2272 pkg.applicationInfo.flags, true);
2273 if (suid == null) {
2274 Log.w(TAG, "Creating application package " + pkgName
2275 + " for shared user failed");
2276 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2277 return null;
2278 }
2279 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2280 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2281 + suid.userId + "): packages=" + suid.packages);
2282 }
2283 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002284
2285 // Just create the setting, don't add it yet. For already existing packages
2286 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2288 destResourceFile, pkg.applicationInfo.flags, true, false);
2289 if (pkgSetting == null) {
2290 Log.w(TAG, "Creating application package " + pkgName + " failed");
2291 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2292 return null;
2293 }
2294 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2295 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2296 }
2297
2298 pkg.applicationInfo.uid = pkgSetting.userId;
2299 pkg.mExtras = pkgSetting;
2300
2301 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
2302 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2303 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2304 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2305 return null;
2306 }
2307 // The signature has changed, but this package is in the system
2308 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002309 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310 // However... if this package is part of a shared user, but it
2311 // doesn't match the signature of the shared user, let's fail.
2312 // What this means is that you can't change the signatures
2313 // associated with an overall shared user, which doesn't seem all
2314 // that unreasonable.
2315 if (pkgSetting.sharedUser != null) {
2316 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2317 pkg.mSignatures, false)) {
2318 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2319 return null;
2320 }
2321 }
2322 removeExisting = true;
2323 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002324
2325 // Verify that this new package doesn't have any content providers
2326 // that conflict with existing packages. Only do this if the
2327 // package isn't already installed, since we don't want to break
2328 // things that are installed.
2329 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2330 int N = pkg.providers.size();
2331 int i;
2332 for (i=0; i<N; i++) {
2333 PackageParser.Provider p = pkg.providers.get(i);
2334 String names[] = p.info.authority.split(";");
2335 for (int j = 0; j < names.length; j++) {
2336 if (mProviders.containsKey(names[j])) {
2337 PackageParser.Provider other = mProviders.get(names[j]);
2338 Log.w(TAG, "Can't install because provider name " + names[j] +
2339 " (in package " + pkg.applicationInfo.packageName +
2340 ") is already used by "
2341 + ((other != null && other.component != null)
2342 ? other.component.getPackageName() : "?"));
2343 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2344 return null;
2345 }
2346 }
2347 }
2348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 }
2350
2351 if (removeExisting) {
2352 if (mInstaller != null) {
2353 int ret = mInstaller.remove(pkgName);
2354 if (ret != 0) {
2355 String msg = "System package " + pkg.packageName
2356 + " could not have data directory erased after signature change.";
2357 reportSettingsProblem(Log.WARN, msg);
2358 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2359 return null;
2360 }
2361 }
2362 Log.w(TAG, "System package " + pkg.packageName
2363 + " signature changed: existing data removed.");
2364 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2365 }
2366
2367 long scanFileTime = scanFile.lastModified();
2368 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2369 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2370 pkg.applicationInfo.processName = fixProcessName(
2371 pkg.applicationInfo.packageName,
2372 pkg.applicationInfo.processName,
2373 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002374 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375
2376 File dataPath;
2377 if (mPlatformPackage == pkg) {
2378 // The system package is special.
2379 dataPath = new File (Environment.getDataDirectory(), "system");
2380 pkg.applicationInfo.dataDir = dataPath.getPath();
2381 } else {
2382 // This is a normal package, need to make its data directory.
2383 dataPath = new File(mAppDataDir, pkgName);
2384 if (dataPath.exists()) {
2385 mOutPermissions[1] = 0;
2386 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2387 if (mOutPermissions[1] == pkg.applicationInfo.uid
2388 || !Process.supportsProcesses()) {
2389 pkg.applicationInfo.dataDir = dataPath.getPath();
2390 } else {
2391 boolean recovered = false;
2392 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2393 // If this is a system app, we can at least delete its
2394 // current data so the application will still work.
2395 if (mInstaller != null) {
2396 int ret = mInstaller.remove(pkgName);
2397 if(ret >= 0) {
2398 // Old data gone!
2399 String msg = "System package " + pkg.packageName
2400 + " has changed from uid: "
2401 + mOutPermissions[1] + " to "
2402 + pkg.applicationInfo.uid + "; old data erased";
2403 reportSettingsProblem(Log.WARN, msg);
2404 recovered = true;
2405
2406 // And now re-install the app.
2407 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2408 pkg.applicationInfo.uid);
2409 if (ret == -1) {
2410 // Ack should not happen!
2411 msg = "System package " + pkg.packageName
2412 + " could not have data directory re-created after delete.";
2413 reportSettingsProblem(Log.WARN, msg);
2414 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2415 return null;
2416 }
2417 }
2418 }
2419 if (!recovered) {
2420 mHasSystemUidErrors = true;
2421 }
2422 }
2423 if (!recovered) {
2424 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2425 + pkg.applicationInfo.uid + "/fs_"
2426 + mOutPermissions[1];
2427 String msg = "Package " + pkg.packageName
2428 + " has mismatched uid: "
2429 + mOutPermissions[1] + " on disk, "
2430 + pkg.applicationInfo.uid + " in settings";
2431 synchronized (mPackages) {
2432 if (!mReportedUidError) {
2433 mReportedUidError = true;
2434 msg = msg + "; read messages:\n"
2435 + mSettings.getReadMessagesLP();
2436 }
2437 reportSettingsProblem(Log.ERROR, msg);
2438 }
2439 }
2440 }
2441 pkg.applicationInfo.dataDir = dataPath.getPath();
2442 } else {
2443 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2444 Log.v(TAG, "Want this data dir: " + dataPath);
2445 //invoke installer to do the actual installation
2446 if (mInstaller != null) {
2447 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2448 pkg.applicationInfo.uid);
2449 if(ret < 0) {
2450 // Error from installer
2451 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2452 return null;
2453 }
2454 } else {
2455 dataPath.mkdirs();
2456 if (dataPath.exists()) {
2457 FileUtils.setPermissions(
2458 dataPath.toString(),
2459 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2460 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2461 }
2462 }
2463 if (dataPath.exists()) {
2464 pkg.applicationInfo.dataDir = dataPath.getPath();
2465 } else {
2466 Log.w(TAG, "Unable to create data directory: " + dataPath);
2467 pkg.applicationInfo.dataDir = null;
2468 }
2469 }
2470 }
2471
2472 // Perform shared library installation and dex validation and
2473 // optimization, if this is not a system app.
2474 if (mInstaller != null) {
2475 String path = scanFile.getPath();
2476 if (scanFileNewer) {
2477 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002478 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2479 if (err != PackageManager.INSTALL_SUCCEEDED) {
2480 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 return null;
2482 }
2483 }
2484
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002485 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2486 pkg.mScanPath = path;
2487
2488 if ((scanMode&SCAN_NO_DEX) == 0) {
2489 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2491 return null;
2492 }
2493 }
2494 }
2495
2496 if (mFactoryTest && pkg.requestedPermissions.contains(
2497 android.Manifest.permission.FACTORY_TEST)) {
2498 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2499 }
2500
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002501 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 if ((scanMode&SCAN_MONITOR) != 0) {
2503 pkg.mPath = destCodeFile.getAbsolutePath();
2504 mAppDirs.put(pkg.mPath, pkg);
2505 }
2506
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002507 // Request the ActivityManager to kill the process(only for existing packages)
2508 // so that we do not end up in a confused state while the user is still using the older
2509 // version of the application while the new one gets installed.
2510 IActivityManager am = ActivityManagerNative.getDefault();
2511 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2512 try {
2513 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2514 pkg.applicationInfo.uid);
2515 } catch (RemoteException e) {
2516 }
2517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002520 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002522 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 int N = pkg.providers.size();
2524 StringBuilder r = null;
2525 int i;
2526 for (i=0; i<N; i++) {
2527 PackageParser.Provider p = pkg.providers.get(i);
2528 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2529 p.info.processName, pkg.applicationInfo.uid);
2530 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2531 p.info.name), p);
2532 p.syncable = p.info.isSyncable;
2533 String names[] = p.info.authority.split(";");
2534 p.info.authority = null;
2535 for (int j = 0; j < names.length; j++) {
2536 if (j == 1 && p.syncable) {
2537 // We only want the first authority for a provider to possibly be
2538 // syncable, so if we already added this provider using a different
2539 // authority clear the syncable flag. We copy the provider before
2540 // changing it because the mProviders object contains a reference
2541 // to a provider that we don't want to change.
2542 // Only do this for the second authority since the resulting provider
2543 // object can be the same for all future authorities for this provider.
2544 p = new PackageParser.Provider(p);
2545 p.syncable = false;
2546 }
2547 if (!mProviders.containsKey(names[j])) {
2548 mProviders.put(names[j], p);
2549 if (p.info.authority == null) {
2550 p.info.authority = names[j];
2551 } else {
2552 p.info.authority = p.info.authority + ";" + names[j];
2553 }
2554 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2555 Log.d(TAG, "Registered content provider: " + names[j] +
2556 ", className = " + p.info.name +
2557 ", isSyncable = " + p.info.isSyncable);
2558 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002559 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 Log.w(TAG, "Skipping provider name " + names[j] +
2561 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002562 "): name already used by "
2563 + ((other != null && other.component != null)
2564 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 }
2566 }
2567 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2568 if (r == null) {
2569 r = new StringBuilder(256);
2570 } else {
2571 r.append(' ');
2572 }
2573 r.append(p.info.name);
2574 }
2575 }
2576 if (r != null) {
2577 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2578 }
2579
2580 N = pkg.services.size();
2581 r = null;
2582 for (i=0; i<N; i++) {
2583 PackageParser.Service s = pkg.services.get(i);
2584 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2585 s.info.processName, pkg.applicationInfo.uid);
2586 mServices.addService(s);
2587 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2588 if (r == null) {
2589 r = new StringBuilder(256);
2590 } else {
2591 r.append(' ');
2592 }
2593 r.append(s.info.name);
2594 }
2595 }
2596 if (r != null) {
2597 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2598 }
2599
2600 N = pkg.receivers.size();
2601 r = null;
2602 for (i=0; i<N; i++) {
2603 PackageParser.Activity a = pkg.receivers.get(i);
2604 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2605 a.info.processName, pkg.applicationInfo.uid);
2606 mReceivers.addActivity(a, "receiver");
2607 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2608 if (r == null) {
2609 r = new StringBuilder(256);
2610 } else {
2611 r.append(' ');
2612 }
2613 r.append(a.info.name);
2614 }
2615 }
2616 if (r != null) {
2617 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2618 }
2619
2620 N = pkg.activities.size();
2621 r = null;
2622 for (i=0; i<N; i++) {
2623 PackageParser.Activity a = pkg.activities.get(i);
2624 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2625 a.info.processName, pkg.applicationInfo.uid);
2626 mActivities.addActivity(a, "activity");
2627 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2628 if (r == null) {
2629 r = new StringBuilder(256);
2630 } else {
2631 r.append(' ');
2632 }
2633 r.append(a.info.name);
2634 }
2635 }
2636 if (r != null) {
2637 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2638 }
2639
2640 N = pkg.permissionGroups.size();
2641 r = null;
2642 for (i=0; i<N; i++) {
2643 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2644 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2645 if (cur == null) {
2646 mPermissionGroups.put(pg.info.name, pg);
2647 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2648 if (r == null) {
2649 r = new StringBuilder(256);
2650 } else {
2651 r.append(' ');
2652 }
2653 r.append(pg.info.name);
2654 }
2655 } else {
2656 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2657 + pg.info.packageName + " ignored: original from "
2658 + cur.info.packageName);
2659 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2660 if (r == null) {
2661 r = new StringBuilder(256);
2662 } else {
2663 r.append(' ');
2664 }
2665 r.append("DUP:");
2666 r.append(pg.info.name);
2667 }
2668 }
2669 }
2670 if (r != null) {
2671 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2672 }
2673
2674 N = pkg.permissions.size();
2675 r = null;
2676 for (i=0; i<N; i++) {
2677 PackageParser.Permission p = pkg.permissions.get(i);
2678 HashMap<String, BasePermission> permissionMap =
2679 p.tree ? mSettings.mPermissionTrees
2680 : mSettings.mPermissions;
2681 p.group = mPermissionGroups.get(p.info.group);
2682 if (p.info.group == null || p.group != null) {
2683 BasePermission bp = permissionMap.get(p.info.name);
2684 if (bp == null) {
2685 bp = new BasePermission(p.info.name, p.info.packageName,
2686 BasePermission.TYPE_NORMAL);
2687 permissionMap.put(p.info.name, bp);
2688 }
2689 if (bp.perm == null) {
2690 if (bp.sourcePackage == null
2691 || bp.sourcePackage.equals(p.info.packageName)) {
2692 BasePermission tree = findPermissionTreeLP(p.info.name);
2693 if (tree == null
2694 || tree.sourcePackage.equals(p.info.packageName)) {
2695 bp.perm = p;
2696 bp.uid = pkg.applicationInfo.uid;
2697 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2698 if (r == null) {
2699 r = new StringBuilder(256);
2700 } else {
2701 r.append(' ');
2702 }
2703 r.append(p.info.name);
2704 }
2705 } else {
2706 Log.w(TAG, "Permission " + p.info.name + " from package "
2707 + p.info.packageName + " ignored: base tree "
2708 + tree.name + " is from package "
2709 + tree.sourcePackage);
2710 }
2711 } else {
2712 Log.w(TAG, "Permission " + p.info.name + " from package "
2713 + p.info.packageName + " ignored: original from "
2714 + bp.sourcePackage);
2715 }
2716 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2717 if (r == null) {
2718 r = new StringBuilder(256);
2719 } else {
2720 r.append(' ');
2721 }
2722 r.append("DUP:");
2723 r.append(p.info.name);
2724 }
2725 } else {
2726 Log.w(TAG, "Permission " + p.info.name + " from package "
2727 + p.info.packageName + " ignored: no group "
2728 + p.group);
2729 }
2730 }
2731 if (r != null) {
2732 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2733 }
2734
2735 N = pkg.instrumentation.size();
2736 r = null;
2737 for (i=0; i<N; i++) {
2738 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2739 a.info.packageName = pkg.applicationInfo.packageName;
2740 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2741 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2742 a.info.dataDir = pkg.applicationInfo.dataDir;
2743 mInstrumentation.put(a.component, a);
2744 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2745 if (r == null) {
2746 r = new StringBuilder(256);
2747 } else {
2748 r.append(' ');
2749 }
2750 r.append(a.info.name);
2751 }
2752 }
2753 if (r != null) {
2754 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2755 }
2756
Dianne Hackborn854060af2009-07-09 18:14:31 -07002757 if (pkg.protectedBroadcasts != null) {
2758 N = pkg.protectedBroadcasts.size();
2759 for (i=0; i<N; i++) {
2760 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2761 }
2762 }
2763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 pkgSetting.setTimeStamp(scanFileTime);
2765 }
2766
2767 return pkg;
2768 }
2769
Dianne Hackbornb1811182009-05-21 15:45:42 -07002770 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2771 File dataPath, File scanFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002772 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002773 final String sharedLibraryABI = Build.CPU_ABI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2775 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2776 final String sharedLibrarySuffix = ".so";
Dianne Hackbornb1811182009-05-21 15:45:42 -07002777 boolean hasNativeCode = false;
2778 boolean installedNativeCode = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 try {
2780 ZipFile zipFile = new ZipFile(scanFile);
2781 Enumeration<ZipEntry> entries =
2782 (Enumeration<ZipEntry>) zipFile.entries();
2783
2784 while (entries.hasMoreElements()) {
2785 ZipEntry entry = entries.nextElement();
2786 if (entry.isDirectory()) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002787 if (!hasNativeCode && entry.getName().startsWith("lib")) {
2788 hasNativeCode = true;
2789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 continue;
2791 }
2792 String entryName = entry.getName();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002793 if (entryName.startsWith("lib/")) {
2794 hasNativeCode = true;
2795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2797 && entryName.endsWith(sharedLibrarySuffix))) {
2798 continue;
2799 }
2800 String libFileName = entryName.substring(
2801 apkLibraryDirectory.length());
2802 if (libFileName.contains("/")
2803 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2804 continue;
2805 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002806
2807 installedNativeCode = true;
2808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2810 File.separator + libFileName;
2811 File sharedLibraryFile = new File(sharedLibraryFilePath);
2812 if (! sharedLibraryFile.exists() ||
2813 sharedLibraryFile.length() != entry.getSize() ||
2814 sharedLibraryFile.lastModified() != entry.getTime()) {
2815 if (Config.LOGD) {
2816 Log.d(TAG, "Caching shared lib " + entry.getName());
2817 }
2818 if (mInstaller == null) {
2819 sharedLibraryDir.mkdir();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 }
2821 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2822 sharedLibraryFile);
2823 }
2824 }
2825 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002826 Log.w(TAG, "Failed to cache package shared libs", e);
2827 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002829
2830 if (hasNativeCode && !installedNativeCode) {
2831 Log.w(TAG, "Install failed: .apk has native code but none for arch "
2832 + Build.CPU_ABI);
2833 return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
2834 }
2835
2836 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 }
2838
2839 private void cacheSharedLibLI(PackageParser.Package pkg,
2840 ZipFile zipFile, ZipEntry entry,
2841 File sharedLibraryDir,
2842 File sharedLibraryFile) throws IOException {
2843 InputStream inputStream = zipFile.getInputStream(entry);
2844 try {
2845 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2846 String tempFilePath = tempFile.getPath();
2847 // XXX package manager can't change owner, so the lib files for
2848 // now need to be left as world readable and owned by the system.
2849 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2850 ! tempFile.setLastModified(entry.getTime()) ||
2851 FileUtils.setPermissions(tempFilePath,
2852 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2853 |FileUtils.S_IROTH, -1, -1) != 0 ||
2854 ! tempFile.renameTo(sharedLibraryFile)) {
2855 // Failed to properly write file.
2856 tempFile.delete();
2857 throw new IOException("Couldn't create cached shared lib "
2858 + sharedLibraryFile + " in " + sharedLibraryDir);
2859 }
2860 } finally {
2861 inputStream.close();
2862 }
2863 }
2864
2865 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2866 if (chatty && Config.LOGD) Log.d(
2867 TAG, "Removing package " + pkg.applicationInfo.packageName );
2868
2869 synchronized (mPackages) {
2870 if (pkg.mPreferredOrder > 0) {
2871 mSettings.mPreferredPackages.remove(pkg);
2872 pkg.mPreferredOrder = 0;
2873 updatePreferredIndicesLP();
2874 }
2875
2876 clearPackagePreferredActivitiesLP(pkg.packageName);
2877
2878 mPackages.remove(pkg.applicationInfo.packageName);
2879 if (pkg.mPath != null) {
2880 mAppDirs.remove(pkg.mPath);
2881 }
2882
2883 PackageSetting ps = (PackageSetting)pkg.mExtras;
2884 if (ps != null && ps.sharedUser != null) {
2885 // XXX don't do this until the data is removed.
2886 if (false) {
2887 ps.sharedUser.packages.remove(ps);
2888 if (ps.sharedUser.packages.size() == 0) {
2889 // Remove.
2890 }
2891 }
2892 }
2893
2894 int N = pkg.providers.size();
2895 StringBuilder r = null;
2896 int i;
2897 for (i=0; i<N; i++) {
2898 PackageParser.Provider p = pkg.providers.get(i);
2899 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2900 p.info.name));
2901 if (p.info.authority == null) {
2902
2903 /* The is another ContentProvider with this authority when
2904 * this app was installed so this authority is null,
2905 * Ignore it as we don't have to unregister the provider.
2906 */
2907 continue;
2908 }
2909 String names[] = p.info.authority.split(";");
2910 for (int j = 0; j < names.length; j++) {
2911 if (mProviders.get(names[j]) == p) {
2912 mProviders.remove(names[j]);
2913 if (chatty && Config.LOGD) Log.d(
2914 TAG, "Unregistered content provider: " + names[j] +
2915 ", className = " + p.info.name +
2916 ", isSyncable = " + p.info.isSyncable);
2917 }
2918 }
2919 if (chatty) {
2920 if (r == null) {
2921 r = new StringBuilder(256);
2922 } else {
2923 r.append(' ');
2924 }
2925 r.append(p.info.name);
2926 }
2927 }
2928 if (r != null) {
2929 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2930 }
2931
2932 N = pkg.services.size();
2933 r = null;
2934 for (i=0; i<N; i++) {
2935 PackageParser.Service s = pkg.services.get(i);
2936 mServices.removeService(s);
2937 if (chatty) {
2938 if (r == null) {
2939 r = new StringBuilder(256);
2940 } else {
2941 r.append(' ');
2942 }
2943 r.append(s.info.name);
2944 }
2945 }
2946 if (r != null) {
2947 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2948 }
2949
2950 N = pkg.receivers.size();
2951 r = null;
2952 for (i=0; i<N; i++) {
2953 PackageParser.Activity a = pkg.receivers.get(i);
2954 mReceivers.removeActivity(a, "receiver");
2955 if (chatty) {
2956 if (r == null) {
2957 r = new StringBuilder(256);
2958 } else {
2959 r.append(' ');
2960 }
2961 r.append(a.info.name);
2962 }
2963 }
2964 if (r != null) {
2965 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2966 }
2967
2968 N = pkg.activities.size();
2969 r = null;
2970 for (i=0; i<N; i++) {
2971 PackageParser.Activity a = pkg.activities.get(i);
2972 mActivities.removeActivity(a, "activity");
2973 if (chatty) {
2974 if (r == null) {
2975 r = new StringBuilder(256);
2976 } else {
2977 r.append(' ');
2978 }
2979 r.append(a.info.name);
2980 }
2981 }
2982 if (r != null) {
2983 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2984 }
2985
2986 N = pkg.permissions.size();
2987 r = null;
2988 for (i=0; i<N; i++) {
2989 PackageParser.Permission p = pkg.permissions.get(i);
2990 boolean tree = false;
2991 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2992 if (bp == null) {
2993 tree = true;
2994 bp = mSettings.mPermissionTrees.get(p.info.name);
2995 }
2996 if (bp != null && bp.perm == p) {
2997 if (bp.type != BasePermission.TYPE_BUILTIN) {
2998 if (tree) {
2999 mSettings.mPermissionTrees.remove(p.info.name);
3000 } else {
3001 mSettings.mPermissions.remove(p.info.name);
3002 }
3003 } else {
3004 bp.perm = null;
3005 }
3006 if (chatty) {
3007 if (r == null) {
3008 r = new StringBuilder(256);
3009 } else {
3010 r.append(' ');
3011 }
3012 r.append(p.info.name);
3013 }
3014 }
3015 }
3016 if (r != null) {
3017 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3018 }
3019
3020 N = pkg.instrumentation.size();
3021 r = null;
3022 for (i=0; i<N; i++) {
3023 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3024 mInstrumentation.remove(a.component);
3025 if (chatty) {
3026 if (r == null) {
3027 r = new StringBuilder(256);
3028 } else {
3029 r.append(' ');
3030 }
3031 r.append(a.info.name);
3032 }
3033 }
3034 if (r != null) {
3035 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3036 }
3037 }
3038 }
3039
3040 private static final boolean isPackageFilename(String name) {
3041 return name != null && name.endsWith(".apk");
3042 }
3043
3044 private void updatePermissionsLP() {
3045 // Make sure there are no dangling permission trees.
3046 Iterator<BasePermission> it = mSettings.mPermissionTrees
3047 .values().iterator();
3048 while (it.hasNext()) {
3049 BasePermission bp = it.next();
3050 if (bp.perm == null) {
3051 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3052 + " from package " + bp.sourcePackage);
3053 it.remove();
3054 }
3055 }
3056
3057 // Make sure all dynamic permissions have been assigned to a package,
3058 // and make sure there are no dangling permissions.
3059 it = mSettings.mPermissions.values().iterator();
3060 while (it.hasNext()) {
3061 BasePermission bp = it.next();
3062 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3063 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3064 + bp.name + " pkg=" + bp.sourcePackage
3065 + " info=" + bp.pendingInfo);
3066 if (bp.perm == null && bp.pendingInfo != null) {
3067 BasePermission tree = findPermissionTreeLP(bp.name);
3068 if (tree != null) {
3069 bp.perm = new PackageParser.Permission(tree.perm.owner,
3070 new PermissionInfo(bp.pendingInfo));
3071 bp.perm.info.packageName = tree.perm.info.packageName;
3072 bp.perm.info.name = bp.name;
3073 bp.uid = tree.uid;
3074 }
3075 }
3076 }
3077 if (bp.perm == null) {
3078 Log.w(TAG, "Removing dangling permission: " + bp.name
3079 + " from package " + bp.sourcePackage);
3080 it.remove();
3081 }
3082 }
3083
3084 // Now update the permissions for all packages, in particular
3085 // replace the granted permissions of the system packages.
3086 for (PackageParser.Package pkg : mPackages.values()) {
3087 grantPermissionsLP(pkg, false);
3088 }
3089 }
3090
3091 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3092 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3093 if (ps == null) {
3094 return;
3095 }
3096 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3097 boolean addedPermission = false;
3098
3099 if (replace) {
3100 ps.permissionsFixed = false;
3101 if (gp == ps) {
3102 gp.grantedPermissions.clear();
3103 gp.gids = mGlobalGids;
3104 }
3105 }
3106
3107 if (gp.gids == null) {
3108 gp.gids = mGlobalGids;
3109 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07003110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 final int N = pkg.requestedPermissions.size();
3112 for (int i=0; i<N; i++) {
3113 String name = pkg.requestedPermissions.get(i);
3114 BasePermission bp = mSettings.mPermissions.get(name);
3115 PackageParser.Permission p = bp != null ? bp.perm : null;
3116 if (false) {
3117 if (gp != ps) {
3118 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3119 + ": " + p);
3120 }
3121 }
3122 if (p != null) {
3123 final String perm = p.info.name;
3124 boolean allowed;
3125 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3126 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3127 allowed = true;
3128 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3129 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003130 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003132 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 == PackageManager.SIGNATURE_MATCH);
3134 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3135 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3136 // For updated system applications, the signatureOrSystem permission
3137 // is granted only if it had been defined by the original application.
3138 if ((pkg.applicationInfo.flags
3139 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3140 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3141 if(sysPs.grantedPermissions.contains(perm)) {
3142 allowed = true;
3143 } else {
3144 allowed = false;
3145 }
3146 } else {
3147 allowed = true;
3148 }
3149 }
3150 }
3151 } else {
3152 allowed = false;
3153 }
3154 if (false) {
3155 if (gp != ps) {
3156 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3157 }
3158 }
3159 if (allowed) {
3160 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3161 && ps.permissionsFixed) {
3162 // If this is an existing, non-system package, then
3163 // we can't add any new permissions to it.
3164 if (!gp.loadedPermissions.contains(perm)) {
3165 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003166 // Except... if this is a permission that was added
3167 // to the platform (note: need to only do this when
3168 // updating the platform).
3169 final int NP = PackageParser.NEW_PERMISSIONS.length;
3170 for (int ip=0; ip<NP; ip++) {
3171 final PackageParser.NewPermissionInfo npi
3172 = PackageParser.NEW_PERMISSIONS[ip];
3173 if (npi.name.equals(perm)
3174 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3175 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003176 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003177 + pkg.packageName);
3178 break;
3179 }
3180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 }
3182 }
3183 if (allowed) {
3184 if (!gp.grantedPermissions.contains(perm)) {
3185 addedPermission = true;
3186 gp.grantedPermissions.add(perm);
3187 gp.gids = appendInts(gp.gids, bp.gids);
3188 }
3189 } else {
3190 Log.w(TAG, "Not granting permission " + perm
3191 + " to package " + pkg.packageName
3192 + " because it was previously installed without");
3193 }
3194 } else {
3195 Log.w(TAG, "Not granting permission " + perm
3196 + " to package " + pkg.packageName
3197 + " (protectionLevel=" + p.info.protectionLevel
3198 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3199 + ")");
3200 }
3201 } else {
3202 Log.w(TAG, "Unknown permission " + name
3203 + " in package " + pkg.packageName);
3204 }
3205 }
3206
3207 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003208 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3209 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 // This is the first that we have heard about this package, so the
3211 // permissions we have now selected are fixed until explicitly
3212 // changed.
3213 ps.permissionsFixed = true;
3214 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3215 }
3216 }
3217
3218 private final class ActivityIntentResolver
3219 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003220 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003221 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003222 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 }
3224
Mihai Preda074edef2009-05-18 17:13:31 +02003225 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003227 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3229 }
3230
Mihai Predaeae850c2009-05-13 10:13:48 +02003231 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3232 ArrayList<PackageParser.Activity> packageActivities) {
3233 if (packageActivities == null) {
3234 return null;
3235 }
3236 mFlags = flags;
3237 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3238 int N = packageActivities.size();
3239 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3240 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003241
3242 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003243 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003244 intentFilters = packageActivities.get(i).intents;
3245 if (intentFilters != null && intentFilters.size() > 0) {
3246 listCut.add(intentFilters);
3247 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003248 }
3249 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3250 }
3251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 public final void addActivity(PackageParser.Activity a, String type) {
3253 mActivities.put(a.component, a);
3254 if (SHOW_INFO || Config.LOGV) Log.v(
3255 TAG, " " + type + " " +
3256 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3257 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3258 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003259 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3261 if (SHOW_INFO || Config.LOGV) {
3262 Log.v(TAG, " IntentFilter:");
3263 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3264 }
3265 if (!intent.debugCheck()) {
3266 Log.w(TAG, "==> For Activity " + a.info.name);
3267 }
3268 addFilter(intent);
3269 }
3270 }
3271
3272 public final void removeActivity(PackageParser.Activity a, String type) {
3273 mActivities.remove(a.component);
3274 if (SHOW_INFO || Config.LOGV) Log.v(
3275 TAG, " " + type + " " +
3276 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3277 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3278 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003279 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3281 if (SHOW_INFO || Config.LOGV) {
3282 Log.v(TAG, " IntentFilter:");
3283 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3284 }
3285 removeFilter(intent);
3286 }
3287 }
3288
3289 @Override
3290 protected boolean allowFilterResult(
3291 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3292 ActivityInfo filterAi = filter.activity.info;
3293 for (int i=dest.size()-1; i>=0; i--) {
3294 ActivityInfo destAi = dest.get(i).activityInfo;
3295 if (destAi.name == filterAi.name
3296 && destAi.packageName == filterAi.packageName) {
3297 return false;
3298 }
3299 }
3300 return true;
3301 }
3302
3303 @Override
3304 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3305 int match) {
3306 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3307 return null;
3308 }
3309 final PackageParser.Activity activity = info.activity;
3310 if (mSafeMode && (activity.info.applicationInfo.flags
3311 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3312 return null;
3313 }
3314 final ResolveInfo res = new ResolveInfo();
3315 res.activityInfo = PackageParser.generateActivityInfo(activity,
3316 mFlags);
3317 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3318 res.filter = info;
3319 }
3320 res.priority = info.getPriority();
3321 res.preferredOrder = activity.owner.mPreferredOrder;
3322 //System.out.println("Result: " + res.activityInfo.className +
3323 // " = " + res.priority);
3324 res.match = match;
3325 res.isDefault = info.hasDefault;
3326 res.labelRes = info.labelRes;
3327 res.nonLocalizedLabel = info.nonLocalizedLabel;
3328 res.icon = info.icon;
3329 return res;
3330 }
3331
3332 @Override
3333 protected void sortResults(List<ResolveInfo> results) {
3334 Collections.sort(results, mResolvePrioritySorter);
3335 }
3336
3337 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003338 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003340 out.print(prefix); out.print(
3341 Integer.toHexString(System.identityHashCode(filter.activity)));
3342 out.print(' ');
3343 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 }
3345
3346// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3347// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3348// final List<ResolveInfo> retList = Lists.newArrayList();
3349// while (i.hasNext()) {
3350// final ResolveInfo resolveInfo = i.next();
3351// if (isEnabledLP(resolveInfo.activityInfo)) {
3352// retList.add(resolveInfo);
3353// }
3354// }
3355// return retList;
3356// }
3357
3358 // Keys are String (activity class name), values are Activity.
3359 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3360 = new HashMap<ComponentName, PackageParser.Activity>();
3361 private int mFlags;
3362 }
3363
3364 private final class ServiceIntentResolver
3365 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003366 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003368 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 }
3370
Mihai Preda074edef2009-05-18 17:13:31 +02003371 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003373 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3375 }
3376
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003377 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3378 ArrayList<PackageParser.Service> packageServices) {
3379 if (packageServices == null) {
3380 return null;
3381 }
3382 mFlags = flags;
3383 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3384 int N = packageServices.size();
3385 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3386 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3387
3388 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3389 for (int i = 0; i < N; ++i) {
3390 intentFilters = packageServices.get(i).intents;
3391 if (intentFilters != null && intentFilters.size() > 0) {
3392 listCut.add(intentFilters);
3393 }
3394 }
3395 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3396 }
3397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 public final void addService(PackageParser.Service s) {
3399 mServices.put(s.component, s);
3400 if (SHOW_INFO || Config.LOGV) Log.v(
3401 TAG, " " + (s.info.nonLocalizedLabel != null
3402 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3403 if (SHOW_INFO || Config.LOGV) Log.v(
3404 TAG, " Class=" + s.info.name);
3405 int NI = s.intents.size();
3406 int j;
3407 for (j=0; j<NI; j++) {
3408 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3409 if (SHOW_INFO || Config.LOGV) {
3410 Log.v(TAG, " IntentFilter:");
3411 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3412 }
3413 if (!intent.debugCheck()) {
3414 Log.w(TAG, "==> For Service " + s.info.name);
3415 }
3416 addFilter(intent);
3417 }
3418 }
3419
3420 public final void removeService(PackageParser.Service s) {
3421 mServices.remove(s.component);
3422 if (SHOW_INFO || Config.LOGV) Log.v(
3423 TAG, " " + (s.info.nonLocalizedLabel != null
3424 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3425 if (SHOW_INFO || Config.LOGV) Log.v(
3426 TAG, " Class=" + s.info.name);
3427 int NI = s.intents.size();
3428 int j;
3429 for (j=0; j<NI; j++) {
3430 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3431 if (SHOW_INFO || Config.LOGV) {
3432 Log.v(TAG, " IntentFilter:");
3433 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3434 }
3435 removeFilter(intent);
3436 }
3437 }
3438
3439 @Override
3440 protected boolean allowFilterResult(
3441 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3442 ServiceInfo filterSi = filter.service.info;
3443 for (int i=dest.size()-1; i>=0; i--) {
3444 ServiceInfo destAi = dest.get(i).serviceInfo;
3445 if (destAi.name == filterSi.name
3446 && destAi.packageName == filterSi.packageName) {
3447 return false;
3448 }
3449 }
3450 return true;
3451 }
3452
3453 @Override
3454 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3455 int match) {
3456 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3457 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3458 return null;
3459 }
3460 final PackageParser.Service service = info.service;
3461 if (mSafeMode && (service.info.applicationInfo.flags
3462 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3463 return null;
3464 }
3465 final ResolveInfo res = new ResolveInfo();
3466 res.serviceInfo = PackageParser.generateServiceInfo(service,
3467 mFlags);
3468 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3469 res.filter = filter;
3470 }
3471 res.priority = info.getPriority();
3472 res.preferredOrder = service.owner.mPreferredOrder;
3473 //System.out.println("Result: " + res.activityInfo.className +
3474 // " = " + res.priority);
3475 res.match = match;
3476 res.isDefault = info.hasDefault;
3477 res.labelRes = info.labelRes;
3478 res.nonLocalizedLabel = info.nonLocalizedLabel;
3479 res.icon = info.icon;
3480 return res;
3481 }
3482
3483 @Override
3484 protected void sortResults(List<ResolveInfo> results) {
3485 Collections.sort(results, mResolvePrioritySorter);
3486 }
3487
3488 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003489 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003491 out.print(prefix); out.print(
3492 Integer.toHexString(System.identityHashCode(filter.service)));
3493 out.print(' ');
3494 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 }
3496
3497// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3498// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3499// final List<ResolveInfo> retList = Lists.newArrayList();
3500// while (i.hasNext()) {
3501// final ResolveInfo resolveInfo = (ResolveInfo) i;
3502// if (isEnabledLP(resolveInfo.serviceInfo)) {
3503// retList.add(resolveInfo);
3504// }
3505// }
3506// return retList;
3507// }
3508
3509 // Keys are String (activity class name), values are Activity.
3510 private final HashMap<ComponentName, PackageParser.Service> mServices
3511 = new HashMap<ComponentName, PackageParser.Service>();
3512 private int mFlags;
3513 };
3514
3515 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3516 new Comparator<ResolveInfo>() {
3517 public int compare(ResolveInfo r1, ResolveInfo r2) {
3518 int v1 = r1.priority;
3519 int v2 = r2.priority;
3520 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3521 if (v1 != v2) {
3522 return (v1 > v2) ? -1 : 1;
3523 }
3524 v1 = r1.preferredOrder;
3525 v2 = r2.preferredOrder;
3526 if (v1 != v2) {
3527 return (v1 > v2) ? -1 : 1;
3528 }
3529 if (r1.isDefault != r2.isDefault) {
3530 return r1.isDefault ? -1 : 1;
3531 }
3532 v1 = r1.match;
3533 v2 = r2.match;
3534 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3535 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3536 }
3537 };
3538
3539 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3540 new Comparator<ProviderInfo>() {
3541 public int compare(ProviderInfo p1, ProviderInfo p2) {
3542 final int v1 = p1.initOrder;
3543 final int v2 = p2.initOrder;
3544 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3545 }
3546 };
3547
3548 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3549 IActivityManager am = ActivityManagerNative.getDefault();
3550 if (am != null) {
3551 try {
3552 final Intent intent = new Intent(action,
3553 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3554 if (extras != null) {
3555 intent.putExtras(extras);
3556 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003557 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 am.broadcastIntent(
3559 null, intent,
3560 null, null, 0, null, null, null, false, false);
3561 } catch (RemoteException ex) {
3562 }
3563 }
3564 }
3565
3566 private final class AppDirObserver extends FileObserver {
3567 public AppDirObserver(String path, int mask, boolean isrom) {
3568 super(path, mask);
3569 mRootDir = path;
3570 mIsRom = isrom;
3571 }
3572
3573 public void onEvent(int event, String path) {
3574 String removedPackage = null;
3575 int removedUid = -1;
3576 String addedPackage = null;
3577 int addedUid = -1;
3578
3579 synchronized (mInstallLock) {
3580 String fullPathStr = null;
3581 File fullPath = null;
3582 if (path != null) {
3583 fullPath = new File(mRootDir, path);
3584 fullPathStr = fullPath.getPath();
3585 }
3586
3587 if (Config.LOGV) Log.v(
3588 TAG, "File " + fullPathStr + " changed: "
3589 + Integer.toHexString(event));
3590
3591 if (!isPackageFilename(path)) {
3592 if (Config.LOGV) Log.v(
3593 TAG, "Ignoring change of non-package file: " + fullPathStr);
3594 return;
3595 }
3596
3597 if ((event&REMOVE_EVENTS) != 0) {
3598 synchronized (mInstallLock) {
3599 PackageParser.Package p = mAppDirs.get(fullPathStr);
3600 if (p != null) {
3601 removePackageLI(p, true);
3602 removedPackage = p.applicationInfo.packageName;
3603 removedUid = p.applicationInfo.uid;
3604 }
3605 }
3606 }
3607
3608 if ((event&ADD_EVENTS) != 0) {
3609 PackageParser.Package p = mAppDirs.get(fullPathStr);
3610 if (p == null) {
3611 p = scanPackageLI(fullPath, fullPath, fullPath,
3612 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3613 PackageParser.PARSE_CHATTY |
3614 PackageParser.PARSE_MUST_BE_APK,
3615 SCAN_MONITOR);
3616 if (p != null) {
3617 synchronized (mPackages) {
3618 grantPermissionsLP(p, false);
3619 }
3620 addedPackage = p.applicationInfo.packageName;
3621 addedUid = p.applicationInfo.uid;
3622 }
3623 }
3624 }
3625
3626 synchronized (mPackages) {
3627 mSettings.writeLP();
3628 }
3629 }
3630
3631 if (removedPackage != null) {
3632 Bundle extras = new Bundle(1);
3633 extras.putInt(Intent.EXTRA_UID, removedUid);
3634 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3635 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3636 }
3637 if (addedPackage != null) {
3638 Bundle extras = new Bundle(1);
3639 extras.putInt(Intent.EXTRA_UID, addedUid);
3640 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3641 }
3642 }
3643
3644 private final String mRootDir;
3645 private final boolean mIsRom;
3646 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 /* Called when a downloaded package installation has been confirmed by the user */
3649 public void installPackage(
3650 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003651 installPackage(packageURI, observer, flags, null);
3652 }
3653
3654 /* Called when a downloaded package installation has been confirmed by the user */
3655 public void installPackage(
3656 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3657 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 mContext.enforceCallingOrSelfPermission(
3659 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 // Queue up an async operation since the package installation may take a little while.
3662 mHandler.post(new Runnable() {
3663 public void run() {
3664 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003665 // Result object to be returned
3666 PackageInstalledInfo res = new PackageInstalledInfo();
3667 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3668 res.uid = -1;
3669 res.pkg = null;
3670 res.removedInfo = new PackageRemovedInfo();
3671 // Make a temporary copy of file from given packageURI
3672 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3673 if (tmpPackageFile != null) {
3674 synchronized (mInstallLock) {
3675 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3676 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 }
3678 if (observer != null) {
3679 try {
3680 observer.packageInstalled(res.name, res.returnCode);
3681 } catch (RemoteException e) {
3682 Log.i(TAG, "Observer no longer exists.");
3683 }
3684 }
3685 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3686 // call appears in the synchronized block above.
3687 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3688 res.removedInfo.sendBroadcast(false, true);
3689 Bundle extras = new Bundle(1);
3690 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003691 final boolean update = res.removedInfo.removedPackage != null;
3692 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3694 }
3695 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3696 res.pkg.applicationInfo.packageName,
3697 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003698 if (update) {
3699 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3700 res.pkg.applicationInfo.packageName,
3701 extras);
3702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 }
3704 Runtime.getRuntime().gc();
3705 }
3706 });
3707 }
3708
3709 class PackageInstalledInfo {
3710 String name;
3711 int uid;
3712 PackageParser.Package pkg;
3713 int returnCode;
3714 PackageRemovedInfo removedInfo;
3715 }
3716
3717 /*
3718 * Install a non-existing package.
3719 */
3720 private void installNewPackageLI(String pkgName,
3721 File tmpPackageFile,
3722 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003723 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003724 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 // Remember this for later, in case we need to rollback this install
3726 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3727 res.name = pkgName;
3728 synchronized(mPackages) {
3729 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3730 // Don't allow installation over an existing package with the same name.
3731 Log.w(TAG, "Attempt to re-install " + pkgName
3732 + " without first uninstalling.");
3733 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3734 return;
3735 }
3736 }
3737 if (destPackageFile.exists()) {
3738 // It's safe to do this because we know (from the above check) that the file
3739 // isn't currently used for an installed package.
3740 destPackageFile.delete();
3741 }
3742 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3743 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3744 destResourceFile, pkg, 0,
3745 SCAN_MONITOR | SCAN_FORCE_DEX
3746 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003747 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3748 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 if (newPackage == null) {
3750 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3751 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3752 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3753 }
3754 } else {
3755 updateSettingsLI(pkgName, tmpPackageFile,
3756 destFilePath, destPackageFile,
3757 destResourceFile, pkg,
3758 newPackage,
3759 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003760 forwardLocked,
3761 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762 res);
3763 // delete the partially installed application. the data directory will have to be
3764 // restored if it was already existing
3765 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3766 // remove package from internal structures. Note that we want deletePackageX to
3767 // delete the package data and cache directories that it created in
3768 // scanPackageLocked, unless those directories existed before we even tried to
3769 // install.
3770 deletePackageLI(
3771 pkgName, true,
3772 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3773 res.removedInfo);
3774 }
3775 }
3776 }
3777
3778 private void replacePackageLI(String pkgName,
3779 File tmpPackageFile,
3780 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003781 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003782 String installerPackageName, PackageInstalledInfo res) {
3783
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003784 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 // First find the old package info and check signatures
3786 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003787 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003788 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3789 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3791 return;
3792 }
3793 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003794 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003796 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003798 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003799 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003801 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003802 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003803 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 }
3805 }
3806
3807 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3808 File tmpPackageFile,
3809 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003810 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003811 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 PackageParser.Package newPackage = null;
3813 String pkgName = deletedPackage.packageName;
3814 boolean deletedPkg = true;
3815 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003816
3817 String oldInstallerPackageName = null;
3818 synchronized (mPackages) {
3819 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3820 }
3821
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003822 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 // First delete the existing package while retaining the data directory
3824 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3825 res.removedInfo)) {
3826 // If the existing package was'nt successfully deleted
3827 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3828 deletedPkg = false;
3829 } else {
3830 // Successfully deleted the old package. Now proceed with re-installation
3831 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3832 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3833 destResourceFile, pkg, parseFlags,
3834 SCAN_MONITOR | SCAN_FORCE_DEX
3835 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003836 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3837 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 if (newPackage == null) {
3839 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3840 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3841 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3842 }
3843 } else {
3844 updateSettingsLI(pkgName, tmpPackageFile,
3845 destFilePath, destPackageFile,
3846 destResourceFile, pkg,
3847 newPackage,
3848 true,
3849 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003850 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 res);
3852 updatedSettings = true;
3853 }
3854 }
3855
3856 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3857 // If we deleted an exisiting package, the old source and resource files that we
3858 // were keeping around in case we needed them (see below) can now be deleted
3859 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3860 final ApplicationInfo installedPackageAppInfo =
3861 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003862 deletePackageResourcesLI(pkgName,
3863 !deletedPackageAppInfo.sourceDir
3864 .equals(installedPackageAppInfo.sourceDir)
3865 ? deletedPackageAppInfo.sourceDir : null,
3866 !deletedPackageAppInfo.publicSourceDir
3867 .equals(installedPackageAppInfo.publicSourceDir)
3868 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003869 //update signature on the new package setting
3870 //this should always succeed, since we checked the
3871 //signature earlier.
3872 synchronized(mPackages) {
3873 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3874 parseFlags, true);
3875 }
3876 } else {
3877 // remove package from internal structures. Note that we want deletePackageX to
3878 // delete the package data and cache directories that it created in
3879 // scanPackageLocked, unless those directories existed before we even tried to
3880 // install.
3881 if(updatedSettings) {
3882 deletePackageLI(
3883 pkgName, true,
3884 PackageManager.DONT_DELETE_DATA,
3885 res.removedInfo);
3886 }
3887 // Since we failed to install the new package we need to restore the old
3888 // package that we deleted.
3889 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003890 File restoreFile = new File(deletedPackage.mPath);
3891 if (restoreFile == null) {
3892 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
3893 return;
3894 }
3895 File restoreTmpFile = createTempPackageFile();
3896 if (restoreTmpFile == null) {
3897 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
3898 return;
3899 }
3900 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
3901 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
3902 return;
3903 }
3904 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
3905 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003907 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003908 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003909 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003910 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
3911 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3912 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
3913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 }
3915 }
3916 }
3917
3918 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3919 File tmpPackageFile,
3920 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003921 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003922 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 PackageParser.Package newPackage = null;
3924 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003925 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 PackageParser.PARSE_IS_SYSTEM;
3927 String packageName = deletedPackage.packageName;
3928 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3929 if (packageName == null) {
3930 Log.w(TAG, "Attempt to delete null packageName.");
3931 return;
3932 }
3933 PackageParser.Package oldPkg;
3934 PackageSetting oldPkgSetting;
3935 synchronized (mPackages) {
3936 oldPkg = mPackages.get(packageName);
3937 oldPkgSetting = mSettings.mPackages.get(packageName);
3938 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3939 (oldPkgSetting == null)) {
3940 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3941 return;
3942 }
3943 }
3944 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3945 res.removedInfo.removedPackage = packageName;
3946 // Remove existing system package
3947 removePackageLI(oldPkg, true);
3948 synchronized (mPackages) {
3949 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3950 }
3951
3952 // Successfully disabled the old package. Now proceed with re-installation
3953 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3954 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3955 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3956 destResourceFile, pkg, parseFlags,
3957 SCAN_MONITOR | SCAN_FORCE_DEX
3958 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003959 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3960 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 if (newPackage == null) {
3962 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3963 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3964 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3965 }
3966 } else {
3967 updateSettingsLI(packageName, tmpPackageFile,
3968 destFilePath, destPackageFile,
3969 destResourceFile, pkg,
3970 newPackage,
3971 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003972 forwardLocked,
3973 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 res);
3975 updatedSettings = true;
3976 }
3977
3978 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3979 //update signature on the new package setting
3980 //this should always succeed, since we checked the
3981 //signature earlier.
3982 synchronized(mPackages) {
3983 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3984 parseFlags, true);
3985 }
3986 } else {
3987 // Re installation failed. Restore old information
3988 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07003989 if (newPackage != null) {
3990 removePackageLI(newPackage, true);
3991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 // Add back the old system package
3993 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3994 oldPkgSetting.resourcePath,
3995 oldPkg, parseFlags,
3996 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003997 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 // Restore the old system information in Settings
3999 synchronized(mPackages) {
4000 if(updatedSettings) {
4001 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004002 mSettings.setInstallerPackageName(packageName,
4003 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 }
4005 mSettings.writeLP();
4006 }
4007 }
4008 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 private void updateSettingsLI(String pkgName, File tmpPackageFile,
4011 String destFilePath, File destPackageFile,
4012 File destResourceFile,
4013 PackageParser.Package pkg,
4014 PackageParser.Package newPackage,
4015 boolean replacingExistingPackage,
4016 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02004017 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 synchronized (mPackages) {
4019 //write settings. the installStatus will be incomplete at this stage.
4020 //note that the new package setting would have already been
4021 //added to mPackages. It hasn't been persisted yet.
4022 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4023 mSettings.writeLP();
4024 }
4025
4026 int retCode = 0;
4027 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4028 retCode = mInstaller.movedex(tmpPackageFile.toString(),
4029 destPackageFile.toString());
4030 if (retCode != 0) {
4031 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
4032 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4033 return;
4034 }
4035 }
4036 // XXX There are probably some big issues here: upon doing
4037 // the rename, we have reached the point of no return (the
4038 // original .apk is gone!), so we can't fail. Yet... we can.
4039 if (!tmpPackageFile.renameTo(destPackageFile)) {
4040 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
4041 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4042 } else {
4043 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4044 destResourceFile,
4045 forwardLocked);
4046 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4047 return;
4048 } else {
4049 Log.d(TAG, "New package installed in " + destPackageFile);
4050 }
4051 }
4052 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4053 if (mInstaller != null) {
4054 mInstaller.rmdex(tmpPackageFile.getPath());
4055 }
4056 }
4057
4058 synchronized (mPackages) {
4059 grantPermissionsLP(newPackage, true);
4060 res.name = pkgName;
4061 res.uid = newPackage.applicationInfo.uid;
4062 res.pkg = newPackage;
4063 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004064 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4066 //to update install status
4067 mSettings.writeLP();
4068 }
4069 }
4070
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004071 private File getFwdLockedResource(String pkgName) {
4072 final String publicZipFileName = pkgName + ".zip";
4073 return new File(mAppInstallDir, publicZipFileName);
4074 }
4075
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004076 private File copyTempInstallFile(Uri pPackageURI,
4077 PackageInstalledInfo res) {
4078 File tmpPackageFile = createTempPackageFile();
4079 int retCode = PackageManager.INSTALL_SUCCEEDED;
4080 if (tmpPackageFile == null) {
4081 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4082 return null;
4083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004084
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004085 if (pPackageURI.getScheme().equals("file")) {
4086 final File srcPackageFile = new File(pPackageURI.getPath());
4087 // We copy the source package file to a temp file and then rename it to the
4088 // destination file in order to eliminate a window where the package directory
4089 // scanner notices the new package file but it's not completely copied yet.
4090 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4091 Log.e(TAG, "Couldn't copy package file to temp file.");
4092 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004094 } else if (pPackageURI.getScheme().equals("content")) {
4095 ParcelFileDescriptor fd = null;
4096 try {
4097 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4098 } catch (FileNotFoundException e) {
4099 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4100 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4101 }
4102 if (fd == null) {
4103 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4104 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4105 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 if (Config.LOGV) {
4107 Log.v(TAG, "Opened file descriptor from download service.");
4108 }
4109 ParcelFileDescriptor.AutoCloseInputStream
4110 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4111 // We copy the source package file to a temp file and then rename it to the
4112 // destination file in order to eliminate a window where the package directory
4113 // scanner notices the new package file but it's not completely copied yet.
4114 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4115 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004116 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004119 } else {
4120 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4121 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4122 }
4123
4124 res.returnCode = retCode;
4125 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4126 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4127 tmpPackageFile.delete();
4128 }
4129 return null;
4130 }
4131 return tmpPackageFile;
4132 }
4133
4134 private void installPackageLI(Uri pPackageURI,
4135 int pFlags, boolean newInstall, String installerPackageName,
4136 File tmpPackageFile, PackageInstalledInfo res) {
4137 String pkgName = null;
4138 boolean forwardLocked = false;
4139 boolean replacingExistingPackage = false;
4140 // Result object to be returned
4141 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4142
4143 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 pkgName = PackageParser.parsePackageName(
4145 tmpPackageFile.getAbsolutePath(), 0);
4146 if (pkgName == null) {
4147 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4148 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4149 break main_flow;
4150 }
4151 res.name = pkgName;
4152 //initialize some variables before installing pkg
4153 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004154 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 ? mDrmAppPrivateInstallDir
4156 : mAppInstallDir;
4157 final File destPackageFile = new File(destDir, pkgFileName);
4158 final String destFilePath = destPackageFile.getAbsolutePath();
4159 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004160 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004161 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 forwardLocked = true;
4163 } else {
4164 destResourceFile = destPackageFile;
4165 }
4166 // Retrieve PackageSettings and parse package
4167 int parseFlags = PackageParser.PARSE_CHATTY;
4168 parseFlags |= mDefParseFlags;
4169 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4170 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07004171 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4173 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4174 if (pkg == null) {
4175 res.returnCode = pp.getParseError();
4176 break main_flow;
4177 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004178 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4179 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4180 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4181 break main_flow;
4182 }
4183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4185 res.returnCode = pp.getParseError();
4186 break main_flow;
4187 }
4188
4189 synchronized (mPackages) {
4190 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004191 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 && mPackages.containsKey(pkgName)) {
4193 replacingExistingPackage = true;
4194 }
4195 }
4196
4197 if(replacingExistingPackage) {
4198 replacePackageLI(pkgName,
4199 tmpPackageFile,
4200 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004201 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 res);
4203 } else {
4204 installNewPackageLI(pkgName,
4205 tmpPackageFile,
4206 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004207 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 res);
4209 }
4210 } finally {
4211 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4212 tmpPackageFile.delete();
4213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 }
4215 }
4216
4217 private int setPermissionsLI(String pkgName,
4218 PackageParser.Package newPackage,
4219 String destFilePath,
4220 File destResourceFile,
4221 boolean forwardLocked) {
4222 int retCode;
4223 if (forwardLocked) {
4224 try {
4225 extractPublicFiles(newPackage, destResourceFile);
4226 } catch (IOException e) {
4227 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4228 " forward-locked app.");
4229 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4230 } finally {
4231 //TODO clean up the extracted public files
4232 }
4233 if (mInstaller != null) {
4234 retCode = mInstaller.setForwardLockPerm(pkgName,
4235 newPackage.applicationInfo.uid);
4236 } else {
4237 final int filePermissions =
4238 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4239 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4240 newPackage.applicationInfo.uid);
4241 }
4242 } else {
4243 final int filePermissions =
4244 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4245 |FileUtils.S_IROTH;
4246 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4247 }
4248 if (retCode != 0) {
4249 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4250 + ". The return code was: " + retCode);
4251 }
4252 return PackageManager.INSTALL_SUCCEEDED;
4253 }
4254
4255 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4256 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4257 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4258 }
4259
4260 private void extractPublicFiles(PackageParser.Package newPackage,
4261 File publicZipFile) throws IOException {
4262 final ZipOutputStream publicZipOutStream =
4263 new ZipOutputStream(new FileOutputStream(publicZipFile));
4264 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4265
4266 // Copy manifest, resources.arsc and res directory to public zip
4267
4268 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4269 while (privateZipEntries.hasMoreElements()) {
4270 final ZipEntry zipEntry = privateZipEntries.nextElement();
4271 final String zipEntryName = zipEntry.getName();
4272 if ("AndroidManifest.xml".equals(zipEntryName)
4273 || "resources.arsc".equals(zipEntryName)
4274 || zipEntryName.startsWith("res/")) {
4275 try {
4276 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4277 } catch (IOException e) {
4278 try {
4279 publicZipOutStream.close();
4280 throw e;
4281 } finally {
4282 publicZipFile.delete();
4283 }
4284 }
4285 }
4286 }
4287
4288 publicZipOutStream.close();
4289 FileUtils.setPermissions(
4290 publicZipFile.getAbsolutePath(),
4291 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4292 -1, -1);
4293 }
4294
4295 private static void copyZipEntry(ZipEntry zipEntry,
4296 ZipFile inZipFile,
4297 ZipOutputStream outZipStream) throws IOException {
4298 byte[] buffer = new byte[4096];
4299 int num;
4300
4301 ZipEntry newEntry;
4302 if (zipEntry.getMethod() == ZipEntry.STORED) {
4303 // Preserve the STORED method of the input entry.
4304 newEntry = new ZipEntry(zipEntry);
4305 } else {
4306 // Create a new entry so that the compressed len is recomputed.
4307 newEntry = new ZipEntry(zipEntry.getName());
4308 }
4309 outZipStream.putNextEntry(newEntry);
4310
4311 InputStream data = inZipFile.getInputStream(zipEntry);
4312 while ((num = data.read(buffer)) > 0) {
4313 outZipStream.write(buffer, 0, num);
4314 }
4315 outZipStream.flush();
4316 }
4317
4318 private void deleteTempPackageFiles() {
4319 FilenameFilter filter = new FilenameFilter() {
4320 public boolean accept(File dir, String name) {
4321 return name.startsWith("vmdl") && name.endsWith(".tmp");
4322 }
4323 };
4324 String tmpFilesList[] = mAppInstallDir.list(filter);
4325 if(tmpFilesList == null) {
4326 return;
4327 }
4328 for(int i = 0; i < tmpFilesList.length; i++) {
4329 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4330 tmpFile.delete();
4331 }
4332 }
4333
4334 private File createTempPackageFile() {
4335 File tmpPackageFile;
4336 try {
4337 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4338 } catch (IOException e) {
4339 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4340 return null;
4341 }
4342 try {
4343 FileUtils.setPermissions(
4344 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4345 -1, -1);
4346 } catch (IOException e) {
4347 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4348 return null;
4349 }
4350 return tmpPackageFile;
4351 }
4352
4353 public void deletePackage(final String packageName,
4354 final IPackageDeleteObserver observer,
4355 final int flags) {
4356 mContext.enforceCallingOrSelfPermission(
4357 android.Manifest.permission.DELETE_PACKAGES, null);
4358 // Queue up an async operation since the package deletion may take a little while.
4359 mHandler.post(new Runnable() {
4360 public void run() {
4361 mHandler.removeCallbacks(this);
4362 final boolean succeded = deletePackageX(packageName, true, true, flags);
4363 if (observer != null) {
4364 try {
4365 observer.packageDeleted(succeded);
4366 } catch (RemoteException e) {
4367 Log.i(TAG, "Observer no longer exists.");
4368 } //end catch
4369 } //end if
4370 } //end run
4371 });
4372 }
4373
4374 /**
4375 * This method is an internal method that could be get invoked either
4376 * to delete an installed package or to clean up a failed installation.
4377 * After deleting an installed package, a broadcast is sent to notify any
4378 * listeners that the package has been installed. For cleaning up a failed
4379 * installation, the broadcast is not necessary since the package's
4380 * installation wouldn't have sent the initial broadcast either
4381 * The key steps in deleting a package are
4382 * deleting the package information in internal structures like mPackages,
4383 * deleting the packages base directories through installd
4384 * updating mSettings to reflect current status
4385 * persisting settings for later use
4386 * sending a broadcast if necessary
4387 */
4388
4389 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4390 boolean deleteCodeAndResources, int flags) {
4391 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004392 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393
4394 synchronized (mInstallLock) {
4395 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4396 }
4397
4398 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004399 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4400 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4401
4402 // If the removed package was a system update, the old system packaged
4403 // was re-enabled; we need to broadcast this information
4404 if (systemUpdate) {
4405 Bundle extras = new Bundle(1);
4406 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4407 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4408
4409 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4410 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 }
4413 return res;
4414 }
4415
4416 static class PackageRemovedInfo {
4417 String removedPackage;
4418 int uid = -1;
4419 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004420 boolean isRemovedPackageSystemUpdate = false;
4421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 void sendBroadcast(boolean fullRemove, boolean replacing) {
4423 Bundle extras = new Bundle(1);
4424 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4425 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4426 if (replacing) {
4427 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4428 }
4429 if (removedPackage != null) {
4430 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4431 }
4432 if (removedUid >= 0) {
4433 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4434 }
4435 }
4436 }
4437
4438 /*
4439 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4440 * flag is not set, the data directory is removed as well.
4441 * make sure this flag is set for partially installed apps. If not its meaningless to
4442 * delete a partially installed application.
4443 */
4444 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4445 int flags) {
4446 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004447 if (outInfo != null) {
4448 outInfo.removedPackage = packageName;
4449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 removePackageLI(p, true);
4451 // Retrieve object to delete permissions for shared user later on
4452 PackageSetting deletedPs;
4453 synchronized (mPackages) {
4454 deletedPs = mSettings.mPackages.get(packageName);
4455 }
4456 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4457 if (mInstaller != null) {
4458 int retCode = mInstaller.remove(packageName);
4459 if (retCode < 0) {
4460 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4461 + packageName + ", retcode=" + retCode);
4462 // we don't consider this to be a failure of the core package deletion
4463 }
4464 } else {
4465 //for emulator
4466 PackageParser.Package pkg = mPackages.get(packageName);
4467 File dataDir = new File(pkg.applicationInfo.dataDir);
4468 dataDir.delete();
4469 }
4470 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004471 if (outInfo != null) {
4472 outInfo.removedUid = mSettings.removePackageLP(packageName);
4473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 }
4475 }
4476 synchronized (mPackages) {
4477 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4478 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004479 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 }
4481 // Save settings now
4482 mSettings.writeLP ();
4483 }
4484 }
4485
4486 /*
4487 * Tries to delete system package.
4488 */
4489 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004490 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 ApplicationInfo applicationInfo = p.applicationInfo;
4492 //applicable for non-partially installed applications only
4493 if (applicationInfo == null) {
4494 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4495 return false;
4496 }
4497 PackageSetting ps = null;
4498 // Confirm if the system package has been updated
4499 // An updated system app can be deleted. This will also have to restore
4500 // the system pkg from system partition
4501 synchronized (mPackages) {
4502 ps = mSettings.getDisabledSystemPkg(p.packageName);
4503 }
4504 if (ps == null) {
4505 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4506 return false;
4507 } else {
4508 Log.i(TAG, "Deleting system pkg from data partition");
4509 }
4510 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004511 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004512 boolean deleteCodeAndResources = false;
4513 if (ps.versionCode < p.mVersionCode) {
4514 // Delete code and resources for downgrades
4515 deleteCodeAndResources = true;
4516 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4517 flags &= ~PackageManager.DONT_DELETE_DATA;
4518 }
4519 } else {
4520 // Preserve data by setting flag
4521 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4522 flags |= PackageManager.DONT_DELETE_DATA;
4523 }
4524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4526 if (!ret) {
4527 return false;
4528 }
4529 synchronized (mPackages) {
4530 // Reinstate the old system package
4531 mSettings.enableSystemPackageLP(p.packageName);
4532 }
4533 // Install the system package
4534 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4535 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4536 SCAN_MONITOR);
4537
4538 if (newPkg == null) {
4539 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4540 return false;
4541 }
4542 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004543 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 mSettings.writeLP();
4545 }
4546 return true;
4547 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004548
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004549 private void deletePackageResourcesLI(String packageName,
4550 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004551 if (sourceDir != null) {
4552 File sourceFile = new File(sourceDir);
4553 if (!sourceFile.exists()) {
4554 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4555 }
4556 // Delete application's code and resources
4557 sourceFile.delete();
4558 if (mInstaller != null) {
4559 int retCode = mInstaller.rmdex(sourceFile.toString());
4560 if (retCode < 0) {
4561 Log.w(TAG, "Couldn't remove dex file for package: "
4562 + packageName + " at location "
4563 + sourceFile.toString() + ", retcode=" + retCode);
4564 // we don't consider this to be a failure of the core package deletion
4565 }
4566 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004567 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004568 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4569 final File publicSourceFile = new File(publicSourceDir);
4570 if (!publicSourceFile.exists()) {
4571 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4572 }
4573 if (publicSourceFile.exists()) {
4574 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004575 }
4576 }
4577 }
4578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4580 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4581 ApplicationInfo applicationInfo = p.applicationInfo;
4582 if (applicationInfo == null) {
4583 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4584 return false;
4585 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004586 if (outInfo != null) {
4587 outInfo.uid = applicationInfo.uid;
4588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589
4590 // Delete package data from internal structures and also remove data if flag is set
4591 removePackageDataLI(p, outInfo, flags);
4592
4593 // Delete application code and resources
4594 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004595 deletePackageResourcesLI(applicationInfo.packageName,
4596 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 }
4598 return true;
4599 }
4600
4601 /*
4602 * This method handles package deletion in general
4603 */
4604 private boolean deletePackageLI(String packageName,
4605 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4606 if (packageName == null) {
4607 Log.w(TAG, "Attempt to delete null packageName.");
4608 return false;
4609 }
4610 PackageParser.Package p;
4611 boolean dataOnly = false;
4612 synchronized (mPackages) {
4613 p = mPackages.get(packageName);
4614 if (p == null) {
4615 //this retrieves partially installed apps
4616 dataOnly = true;
4617 PackageSetting ps = mSettings.mPackages.get(packageName);
4618 if (ps == null) {
4619 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4620 return false;
4621 }
4622 p = ps.pkg;
4623 }
4624 }
4625 if (p == null) {
4626 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4627 return false;
4628 }
4629
4630 if (dataOnly) {
4631 // Delete application data first
4632 removePackageDataLI(p, outInfo, flags);
4633 return true;
4634 }
4635 // At this point the package should have ApplicationInfo associated with it
4636 if (p.applicationInfo == null) {
4637 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4638 return false;
4639 }
4640 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4641 Log.i(TAG, "Removing system package:"+p.packageName);
4642 // When an updated system application is deleted we delete the existing resources as well and
4643 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004644 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 }
4646 Log.i(TAG, "Removing non-system package:"+p.packageName);
4647 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4648 }
4649
4650 public void clearApplicationUserData(final String packageName,
4651 final IPackageDataObserver observer) {
4652 mContext.enforceCallingOrSelfPermission(
4653 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4654 // Queue up an async operation since the package deletion may take a little while.
4655 mHandler.post(new Runnable() {
4656 public void run() {
4657 mHandler.removeCallbacks(this);
4658 final boolean succeeded;
4659 synchronized (mInstallLock) {
4660 succeeded = clearApplicationUserDataLI(packageName);
4661 }
4662 if (succeeded) {
4663 // invoke DeviceStorageMonitor's update method to clear any notifications
4664 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4665 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4666 if (dsm != null) {
4667 dsm.updateMemory();
4668 }
4669 }
4670 if(observer != null) {
4671 try {
4672 observer.onRemoveCompleted(packageName, succeeded);
4673 } catch (RemoteException e) {
4674 Log.i(TAG, "Observer no longer exists.");
4675 }
4676 } //end if observer
4677 } //end run
4678 });
4679 }
4680
4681 private boolean clearApplicationUserDataLI(String packageName) {
4682 if (packageName == null) {
4683 Log.w(TAG, "Attempt to delete null packageName.");
4684 return false;
4685 }
4686 PackageParser.Package p;
4687 boolean dataOnly = false;
4688 synchronized (mPackages) {
4689 p = mPackages.get(packageName);
4690 if(p == null) {
4691 dataOnly = true;
4692 PackageSetting ps = mSettings.mPackages.get(packageName);
4693 if((ps == null) || (ps.pkg == null)) {
4694 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4695 return false;
4696 }
4697 p = ps.pkg;
4698 }
4699 }
4700 if(!dataOnly) {
4701 //need to check this only for fully installed applications
4702 if (p == null) {
4703 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4704 return false;
4705 }
4706 final ApplicationInfo applicationInfo = p.applicationInfo;
4707 if (applicationInfo == null) {
4708 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4709 return false;
4710 }
4711 }
4712 if (mInstaller != null) {
4713 int retCode = mInstaller.clearUserData(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 deleteApplicationCacheFiles(final String packageName,
4724 final IPackageDataObserver observer) {
4725 mContext.enforceCallingOrSelfPermission(
4726 android.Manifest.permission.DELETE_CACHE_FILES, 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 final boolean succeded;
4732 synchronized (mInstallLock) {
4733 succeded = deleteApplicationCacheFilesLI(packageName);
4734 }
4735 if(observer != null) {
4736 try {
4737 observer.onRemoveCompleted(packageName, succeded);
4738 } catch (RemoteException e) {
4739 Log.i(TAG, "Observer no longer exists.");
4740 }
4741 } //end if observer
4742 } //end run
4743 });
4744 }
4745
4746 private boolean deleteApplicationCacheFilesLI(String packageName) {
4747 if (packageName == null) {
4748 Log.w(TAG, "Attempt to delete null packageName.");
4749 return false;
4750 }
4751 PackageParser.Package p;
4752 synchronized (mPackages) {
4753 p = mPackages.get(packageName);
4754 }
4755 if (p == null) {
4756 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4757 return false;
4758 }
4759 final ApplicationInfo applicationInfo = p.applicationInfo;
4760 if (applicationInfo == null) {
4761 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4762 return false;
4763 }
4764 if (mInstaller != null) {
4765 int retCode = mInstaller.deleteCacheFiles(packageName);
4766 if (retCode < 0) {
4767 Log.w(TAG, "Couldn't remove cache files for package: "
4768 + packageName);
4769 return false;
4770 }
4771 }
4772 return true;
4773 }
4774
4775 public void getPackageSizeInfo(final String packageName,
4776 final IPackageStatsObserver observer) {
4777 mContext.enforceCallingOrSelfPermission(
4778 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4779 // Queue up an async operation since the package deletion may take a little while.
4780 mHandler.post(new Runnable() {
4781 public void run() {
4782 mHandler.removeCallbacks(this);
4783 PackageStats lStats = new PackageStats(packageName);
4784 final boolean succeded;
4785 synchronized (mInstallLock) {
4786 succeded = getPackageSizeInfoLI(packageName, lStats);
4787 }
4788 if(observer != null) {
4789 try {
4790 observer.onGetStatsCompleted(lStats, succeded);
4791 } catch (RemoteException e) {
4792 Log.i(TAG, "Observer no longer exists.");
4793 }
4794 } //end if observer
4795 } //end run
4796 });
4797 }
4798
4799 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4800 if (packageName == null) {
4801 Log.w(TAG, "Attempt to get size of null packageName.");
4802 return false;
4803 }
4804 PackageParser.Package p;
4805 boolean dataOnly = false;
4806 synchronized (mPackages) {
4807 p = mPackages.get(packageName);
4808 if(p == null) {
4809 dataOnly = true;
4810 PackageSetting ps = mSettings.mPackages.get(packageName);
4811 if((ps == null) || (ps.pkg == null)) {
4812 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4813 return false;
4814 }
4815 p = ps.pkg;
4816 }
4817 }
4818 String publicSrcDir = null;
4819 if(!dataOnly) {
4820 final ApplicationInfo applicationInfo = p.applicationInfo;
4821 if (applicationInfo == null) {
4822 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4823 return false;
4824 }
4825 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4826 }
4827 if (mInstaller != null) {
4828 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4829 publicSrcDir, pStats);
4830 if (res < 0) {
4831 return false;
4832 } else {
4833 return true;
4834 }
4835 }
4836 return true;
4837 }
4838
4839
4840 public void addPackageToPreferred(String packageName) {
4841 mContext.enforceCallingOrSelfPermission(
4842 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4843
4844 synchronized (mPackages) {
4845 PackageParser.Package p = mPackages.get(packageName);
4846 if (p == null) {
4847 return;
4848 }
4849 PackageSetting ps = (PackageSetting)p.mExtras;
4850 if (ps != null) {
4851 mSettings.mPreferredPackages.remove(ps);
4852 mSettings.mPreferredPackages.add(0, ps);
4853 updatePreferredIndicesLP();
4854 mSettings.writeLP();
4855 }
4856 }
4857 }
4858
4859 public void removePackageFromPreferred(String packageName) {
4860 mContext.enforceCallingOrSelfPermission(
4861 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4862
4863 synchronized (mPackages) {
4864 PackageParser.Package p = mPackages.get(packageName);
4865 if (p == null) {
4866 return;
4867 }
4868 if (p.mPreferredOrder > 0) {
4869 PackageSetting ps = (PackageSetting)p.mExtras;
4870 if (ps != null) {
4871 mSettings.mPreferredPackages.remove(ps);
4872 p.mPreferredOrder = 0;
4873 updatePreferredIndicesLP();
4874 mSettings.writeLP();
4875 }
4876 }
4877 }
4878 }
4879
4880 private void updatePreferredIndicesLP() {
4881 final ArrayList<PackageSetting> pkgs
4882 = mSettings.mPreferredPackages;
4883 final int N = pkgs.size();
4884 for (int i=0; i<N; i++) {
4885 pkgs.get(i).pkg.mPreferredOrder = N - i;
4886 }
4887 }
4888
4889 public List<PackageInfo> getPreferredPackages(int flags) {
4890 synchronized (mPackages) {
4891 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4892 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4893 final int N = pref.size();
4894 for (int i=0; i<N; i++) {
4895 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4896 }
4897 return res;
4898 }
4899 }
4900
4901 public void addPreferredActivity(IntentFilter filter, int match,
4902 ComponentName[] set, ComponentName activity) {
4903 mContext.enforceCallingOrSelfPermission(
4904 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4905
4906 synchronized (mPackages) {
4907 Log.i(TAG, "Adding preferred activity " + activity + ":");
4908 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4909 mSettings.mPreferredActivities.addFilter(
4910 new PreferredActivity(filter, match, set, activity));
4911 mSettings.writeLP();
4912 }
4913 }
4914
Satish Sampath8dbe6122009-06-02 23:35:54 +01004915 public void replacePreferredActivity(IntentFilter filter, int match,
4916 ComponentName[] set, ComponentName activity) {
4917 mContext.enforceCallingOrSelfPermission(
4918 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4919 if (filter.countActions() != 1) {
4920 throw new IllegalArgumentException(
4921 "replacePreferredActivity expects filter to have only 1 action.");
4922 }
4923 if (filter.countCategories() != 1) {
4924 throw new IllegalArgumentException(
4925 "replacePreferredActivity expects filter to have only 1 category.");
4926 }
4927 if (filter.countDataAuthorities() != 0
4928 || filter.countDataPaths() != 0
4929 || filter.countDataSchemes() != 0
4930 || filter.countDataTypes() != 0) {
4931 throw new IllegalArgumentException(
4932 "replacePreferredActivity expects filter to have no data authorities, " +
4933 "paths, schemes or types.");
4934 }
4935 synchronized (mPackages) {
4936 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4937 String action = filter.getAction(0);
4938 String category = filter.getCategory(0);
4939 while (it.hasNext()) {
4940 PreferredActivity pa = it.next();
4941 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
4942 it.remove();
4943 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
4944 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4945 }
4946 }
4947 addPreferredActivity(filter, match, set, activity);
4948 }
4949 }
4950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 public void clearPackagePreferredActivities(String packageName) {
4952 mContext.enforceCallingOrSelfPermission(
4953 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4954
4955 synchronized (mPackages) {
4956 if (clearPackagePreferredActivitiesLP(packageName)) {
4957 mSettings.writeLP();
4958 }
4959 }
4960 }
4961
4962 boolean clearPackagePreferredActivitiesLP(String packageName) {
4963 boolean changed = false;
4964 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4965 while (it.hasNext()) {
4966 PreferredActivity pa = it.next();
4967 if (pa.mActivity.getPackageName().equals(packageName)) {
4968 it.remove();
4969 changed = true;
4970 }
4971 }
4972 return changed;
4973 }
4974
4975 public int getPreferredActivities(List<IntentFilter> outFilters,
4976 List<ComponentName> outActivities, String packageName) {
4977
4978 int num = 0;
4979 synchronized (mPackages) {
4980 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4981 while (it.hasNext()) {
4982 PreferredActivity pa = it.next();
4983 if (packageName == null
4984 || pa.mActivity.getPackageName().equals(packageName)) {
4985 if (outFilters != null) {
4986 outFilters.add(new IntentFilter(pa));
4987 }
4988 if (outActivities != null) {
4989 outActivities.add(pa.mActivity);
4990 }
4991 }
4992 }
4993 }
4994
4995 return num;
4996 }
4997
4998 public void setApplicationEnabledSetting(String appPackageName,
4999 int newState, int flags) {
5000 setEnabledSetting(appPackageName, null, newState, flags);
5001 }
5002
5003 public void setComponentEnabledSetting(ComponentName componentName,
5004 int newState, int flags) {
5005 setEnabledSetting(componentName.getPackageName(),
5006 componentName.getClassName(), newState, flags);
5007 }
5008
5009 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005010 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5012 || newState == COMPONENT_ENABLED_STATE_ENABLED
5013 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5014 throw new IllegalArgumentException("Invalid new component state: "
5015 + newState);
5016 }
5017 PackageSetting pkgSetting;
5018 final int uid = Binder.getCallingUid();
5019 final int permission = mContext.checkCallingPermission(
5020 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5021 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005022 boolean sendNow = false;
5023 boolean isApp = (className == null);
5024 String key = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 int packageUid = -1;
5026 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005027 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005029 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005031 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 }
5033 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005034 "Unknown component: " + packageName
5035 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 }
5037 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5038 throw new SecurityException(
5039 "Permission Denial: attempt to change component state from pid="
5040 + Binder.getCallingPid()
5041 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5042 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005043 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 // We're dealing with an application/package level state change
5045 pkgSetting.enabled = newState;
5046 } else {
5047 // We're dealing with a component level state change
5048 switch (newState) {
5049 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005050 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 break;
5052 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005053 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 break;
5055 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005056 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 break;
5058 default:
5059 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005060 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 }
5062 }
5063 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005064 packageUid = pkgSetting.userId;
5065 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5066 sendNow = true;
5067 // Purge entry from pending broadcast list if another one exists already
5068 // since we are sending one right away.
5069 if (mPendingBroadcasts.get(key) != null) {
5070 mPendingBroadcasts.remove(key);
5071 // Can ignore empty list since its handled in the handler anyway
5072 }
5073 } else {
5074 if (mPendingBroadcasts.get(key) == null) {
5075 mPendingBroadcasts.put(key, packageName);
5076 }
5077 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5078 // Schedule a message
5079 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5080 }
5081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 long callingId = Binder.clearCallingIdentity();
5085 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005086 if (sendNow) {
5087 sendPackageChangedBroadcast(packageName,
5088 (flags&PackageManager.DONT_KILL_APP) != 0, key, packageUid);
5089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 } finally {
5091 Binder.restoreCallingIdentity(callingId);
5092 }
5093 }
5094
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005095 private void sendPackageChangedBroadcast(String packageName,
5096 boolean killFlag, String componentName, int packageUid) {
5097 Bundle extras = new Bundle(2);
5098 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentName);
5099 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5100 extras.putInt(Intent.EXTRA_UID, packageUid);
5101 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
5102 }
5103
Jacek Surazski65e13172009-04-28 15:26:38 +02005104 public String getInstallerPackageName(String packageName) {
5105 synchronized (mPackages) {
5106 PackageSetting pkg = mSettings.mPackages.get(packageName);
5107 if (pkg == null) {
5108 throw new IllegalArgumentException("Unknown package: " + packageName);
5109 }
5110 return pkg.installerPackageName;
5111 }
5112 }
5113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 public int getApplicationEnabledSetting(String appPackageName) {
5115 synchronized (mPackages) {
5116 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5117 if (pkg == null) {
5118 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5119 }
5120 return pkg.enabled;
5121 }
5122 }
5123
5124 public int getComponentEnabledSetting(ComponentName componentName) {
5125 synchronized (mPackages) {
5126 final String packageNameStr = componentName.getPackageName();
5127 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5128 if (pkg == null) {
5129 throw new IllegalArgumentException("Unknown component: " + componentName);
5130 }
5131 final String classNameStr = componentName.getClassName();
5132 return pkg.currentEnabledStateLP(classNameStr);
5133 }
5134 }
5135
5136 public void enterSafeMode() {
5137 if (!mSystemReady) {
5138 mSafeMode = true;
5139 }
5140 }
5141
5142 public void systemReady() {
5143 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005144
5145 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005146 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005147 mContext.getContentResolver(),
5148 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005149 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005150 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005151 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
5154
5155 public boolean isSafeMode() {
5156 return mSafeMode;
5157 }
5158
5159 public boolean hasSystemUidErrors() {
5160 return mHasSystemUidErrors;
5161 }
5162
5163 static String arrayToString(int[] array) {
5164 StringBuffer buf = new StringBuffer(128);
5165 buf.append('[');
5166 if (array != null) {
5167 for (int i=0; i<array.length; i++) {
5168 if (i > 0) buf.append(", ");
5169 buf.append(array[i]);
5170 }
5171 }
5172 buf.append(']');
5173 return buf.toString();
5174 }
5175
5176 @Override
5177 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5178 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5179 != PackageManager.PERMISSION_GRANTED) {
5180 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5181 + Binder.getCallingPid()
5182 + ", uid=" + Binder.getCallingUid()
5183 + " without permission "
5184 + android.Manifest.permission.DUMP);
5185 return;
5186 }
5187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188 synchronized (mPackages) {
5189 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005190 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 pw.println(" ");
5192 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005193 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 pw.println(" ");
5195 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005196 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 pw.println(" ");
5198 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005199 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 pw.println(" ");
5201 pw.println("Preferred Packages:");
5202 {
5203 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005204 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 }
5206 }
5207 pw.println(" ");
5208 pw.println("Permissions:");
5209 {
5210 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005211 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5212 pw.print(Integer.toHexString(System.identityHashCode(p)));
5213 pw.println("):");
5214 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5215 pw.print(" uid="); pw.print(p.uid);
5216 pw.print(" gids="); pw.print(arrayToString(p.gids));
5217 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 }
5219 }
5220 pw.println(" ");
5221 pw.println("Packages:");
5222 {
5223 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005224 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5225 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5226 pw.println("):");
5227 pw.print(" userId="); pw.print(ps.userId);
5228 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5229 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5230 pw.print(" pkg="); pw.println(ps.pkg);
5231 pw.print(" codePath="); pw.println(ps.codePathString);
5232 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005234 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005235 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005236 pw.print(" supportsScreens=[");
5237 boolean first = true;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005238 if ((ps.pkg.applicationInfo.flags &
5239 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005240 if (!first) pw.print(", ");
5241 first = false;
5242 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005243 }
5244 if ((ps.pkg.applicationInfo.flags &
5245 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005246 if (!first) pw.print(", ");
5247 first = false;
5248 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005249 }
5250 if ((ps.pkg.applicationInfo.flags &
5251 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005252 if (!first) pw.print(", ");
5253 first = false;
5254 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005255 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005256 if ((ps.pkg.applicationInfo.flags &
5257 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005258 if (!first) pw.print(", ");
5259 first = false;
5260 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005261 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005262 if ((ps.pkg.applicationInfo.flags &
5263 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5264 if (!first) pw.print(", ");
5265 first = false;
5266 pw.print("anyDensity");
5267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005269 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005270 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5271 pw.print(" signatures="); pw.println(ps.signatures);
5272 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5273 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5274 pw.print(" installStatus="); pw.print(ps.installStatus);
5275 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 if (ps.disabledComponents.size() > 0) {
5277 pw.println(" disabledComponents:");
5278 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005279 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
5281 }
5282 if (ps.enabledComponents.size() > 0) {
5283 pw.println(" enabledComponents:");
5284 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005285 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 }
5287 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005288 if (ps.grantedPermissions.size() > 0) {
5289 pw.println(" grantedPermissions:");
5290 for (String s : ps.grantedPermissions) {
5291 pw.print(" "); pw.println(s);
5292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005294 if (ps.loadedPermissions.size() > 0) {
5295 pw.println(" loadedPermissions:");
5296 for (String s : ps.loadedPermissions) {
5297 pw.print(" "); pw.println(s);
5298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 }
5300 }
5301 }
5302 pw.println(" ");
5303 pw.println("Shared Users:");
5304 {
5305 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005306 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5307 pw.print(Integer.toHexString(System.identityHashCode(su)));
5308 pw.println("):");
5309 pw.print(" userId="); pw.print(su.userId);
5310 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 pw.println(" grantedPermissions:");
5312 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005313 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 }
5315 pw.println(" loadedPermissions:");
5316 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005317 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 }
5319 }
5320 }
5321 pw.println(" ");
5322 pw.println("Settings parse messages:");
5323 pw.println(mSettings.mReadMessages.toString());
5324 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005325
5326 synchronized (mProviders) {
5327 pw.println(" ");
5328 pw.println("Registered ContentProviders:");
5329 for (PackageParser.Provider p : mProviders.values()) {
5330 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5331 pw.println(p.toString());
5332 }
5333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 }
5335
5336 static final class BasePermission {
5337 final static int TYPE_NORMAL = 0;
5338 final static int TYPE_BUILTIN = 1;
5339 final static int TYPE_DYNAMIC = 2;
5340
5341 final String name;
5342 final String sourcePackage;
5343 final int type;
5344 PackageParser.Permission perm;
5345 PermissionInfo pendingInfo;
5346 int uid;
5347 int[] gids;
5348
5349 BasePermission(String _name, String _sourcePackage, int _type) {
5350 name = _name;
5351 sourcePackage = _sourcePackage;
5352 type = _type;
5353 }
5354 }
5355
5356 static class PackageSignatures {
5357 private Signature[] mSignatures;
5358
5359 PackageSignatures(Signature[] sigs) {
5360 assignSignatures(sigs);
5361 }
5362
5363 PackageSignatures() {
5364 }
5365
5366 void writeXml(XmlSerializer serializer, String tagName,
5367 ArrayList<Signature> pastSignatures) throws IOException {
5368 if (mSignatures == null) {
5369 return;
5370 }
5371 serializer.startTag(null, tagName);
5372 serializer.attribute(null, "count",
5373 Integer.toString(mSignatures.length));
5374 for (int i=0; i<mSignatures.length; i++) {
5375 serializer.startTag(null, "cert");
5376 final Signature sig = mSignatures[i];
5377 final int sigHash = sig.hashCode();
5378 final int numPast = pastSignatures.size();
5379 int j;
5380 for (j=0; j<numPast; j++) {
5381 Signature pastSig = pastSignatures.get(j);
5382 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5383 serializer.attribute(null, "index", Integer.toString(j));
5384 break;
5385 }
5386 }
5387 if (j >= numPast) {
5388 pastSignatures.add(sig);
5389 serializer.attribute(null, "index", Integer.toString(numPast));
5390 serializer.attribute(null, "key", sig.toCharsString());
5391 }
5392 serializer.endTag(null, "cert");
5393 }
5394 serializer.endTag(null, tagName);
5395 }
5396
5397 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5398 throws IOException, XmlPullParserException {
5399 String countStr = parser.getAttributeValue(null, "count");
5400 if (countStr == null) {
5401 reportSettingsProblem(Log.WARN,
5402 "Error in package manager settings: <signatures> has"
5403 + " no count at " + parser.getPositionDescription());
5404 XmlUtils.skipCurrentTag(parser);
5405 }
5406 final int count = Integer.parseInt(countStr);
5407 mSignatures = new Signature[count];
5408 int pos = 0;
5409
5410 int outerDepth = parser.getDepth();
5411 int type;
5412 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5413 && (type != XmlPullParser.END_TAG
5414 || parser.getDepth() > outerDepth)) {
5415 if (type == XmlPullParser.END_TAG
5416 || type == XmlPullParser.TEXT) {
5417 continue;
5418 }
5419
5420 String tagName = parser.getName();
5421 if (tagName.equals("cert")) {
5422 if (pos < count) {
5423 String index = parser.getAttributeValue(null, "index");
5424 if (index != null) {
5425 try {
5426 int idx = Integer.parseInt(index);
5427 String key = parser.getAttributeValue(null, "key");
5428 if (key == null) {
5429 if (idx >= 0 && idx < pastSignatures.size()) {
5430 Signature sig = pastSignatures.get(idx);
5431 if (sig != null) {
5432 mSignatures[pos] = pastSignatures.get(idx);
5433 pos++;
5434 } else {
5435 reportSettingsProblem(Log.WARN,
5436 "Error in package manager settings: <cert> "
5437 + "index " + index + " is not defined at "
5438 + parser.getPositionDescription());
5439 }
5440 } else {
5441 reportSettingsProblem(Log.WARN,
5442 "Error in package manager settings: <cert> "
5443 + "index " + index + " is out of bounds at "
5444 + parser.getPositionDescription());
5445 }
5446 } else {
5447 while (pastSignatures.size() <= idx) {
5448 pastSignatures.add(null);
5449 }
5450 Signature sig = new Signature(key);
5451 pastSignatures.set(idx, sig);
5452 mSignatures[pos] = sig;
5453 pos++;
5454 }
5455 } catch (NumberFormatException e) {
5456 reportSettingsProblem(Log.WARN,
5457 "Error in package manager settings: <cert> "
5458 + "index " + index + " is not a number at "
5459 + parser.getPositionDescription());
5460 }
5461 } else {
5462 reportSettingsProblem(Log.WARN,
5463 "Error in package manager settings: <cert> has"
5464 + " no index at " + parser.getPositionDescription());
5465 }
5466 } else {
5467 reportSettingsProblem(Log.WARN,
5468 "Error in package manager settings: too "
5469 + "many <cert> tags, expected " + count
5470 + " at " + parser.getPositionDescription());
5471 }
5472 } else {
5473 reportSettingsProblem(Log.WARN,
5474 "Unknown element under <cert>: "
5475 + parser.getName());
5476 }
5477 XmlUtils.skipCurrentTag(parser);
5478 }
5479
5480 if (pos < count) {
5481 // Should never happen -- there is an error in the written
5482 // settings -- but if it does we don't want to generate
5483 // a bad array.
5484 Signature[] newSigs = new Signature[pos];
5485 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5486 mSignatures = newSigs;
5487 }
5488 }
5489
5490 /**
5491 * If any of the given 'sigs' is contained in the existing signatures,
5492 * then completely replace the current signatures with the ones in
5493 * 'sigs'. This is used for updating an existing package to a newly
5494 * installed version.
5495 */
5496 boolean updateSignatures(Signature[] sigs, boolean update) {
5497 if (mSignatures == null) {
5498 if (update) {
5499 assignSignatures(sigs);
5500 }
5501 return true;
5502 }
5503 if (sigs == null) {
5504 return false;
5505 }
5506
5507 for (int i=0; i<sigs.length; i++) {
5508 Signature sig = sigs[i];
5509 for (int j=0; j<mSignatures.length; j++) {
5510 if (mSignatures[j].equals(sig)) {
5511 if (update) {
5512 assignSignatures(sigs);
5513 }
5514 return true;
5515 }
5516 }
5517 }
5518 return false;
5519 }
5520
5521 /**
5522 * If any of the given 'sigs' is contained in the existing signatures,
5523 * then add in any new signatures found in 'sigs'. This is used for
5524 * including a new package into an existing shared user id.
5525 */
5526 boolean mergeSignatures(Signature[] sigs, boolean update) {
5527 if (mSignatures == null) {
5528 if (update) {
5529 assignSignatures(sigs);
5530 }
5531 return true;
5532 }
5533 if (sigs == null) {
5534 return false;
5535 }
5536
5537 Signature[] added = null;
5538 int addedCount = 0;
5539 boolean haveMatch = false;
5540 for (int i=0; i<sigs.length; i++) {
5541 Signature sig = sigs[i];
5542 boolean found = false;
5543 for (int j=0; j<mSignatures.length; j++) {
5544 if (mSignatures[j].equals(sig)) {
5545 found = true;
5546 haveMatch = true;
5547 break;
5548 }
5549 }
5550
5551 if (!found) {
5552 if (added == null) {
5553 added = new Signature[sigs.length];
5554 }
5555 added[i] = sig;
5556 addedCount++;
5557 }
5558 }
5559
5560 if (!haveMatch) {
5561 // Nothing matched -- reject the new signatures.
5562 return false;
5563 }
5564 if (added == null) {
5565 // Completely matched -- nothing else to do.
5566 return true;
5567 }
5568
5569 // Add additional signatures in.
5570 if (update) {
5571 Signature[] total = new Signature[addedCount+mSignatures.length];
5572 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5573 int j = mSignatures.length;
5574 for (int i=0; i<added.length; i++) {
5575 if (added[i] != null) {
5576 total[j] = added[i];
5577 j++;
5578 }
5579 }
5580 mSignatures = total;
5581 }
5582 return true;
5583 }
5584
5585 private void assignSignatures(Signature[] sigs) {
5586 if (sigs == null) {
5587 mSignatures = null;
5588 return;
5589 }
5590 mSignatures = new Signature[sigs.length];
5591 for (int i=0; i<sigs.length; i++) {
5592 mSignatures[i] = sigs[i];
5593 }
5594 }
5595
5596 @Override
5597 public String toString() {
5598 StringBuffer buf = new StringBuffer(128);
5599 buf.append("PackageSignatures{");
5600 buf.append(Integer.toHexString(System.identityHashCode(this)));
5601 buf.append(" [");
5602 if (mSignatures != null) {
5603 for (int i=0; i<mSignatures.length; i++) {
5604 if (i > 0) buf.append(", ");
5605 buf.append(Integer.toHexString(
5606 System.identityHashCode(mSignatures[i])));
5607 }
5608 }
5609 buf.append("]}");
5610 return buf.toString();
5611 }
5612 }
5613
5614 static class PreferredActivity extends IntentFilter {
5615 final int mMatch;
5616 final String[] mSetPackages;
5617 final String[] mSetClasses;
5618 final String[] mSetComponents;
5619 final ComponentName mActivity;
5620 final String mShortActivity;
5621 String mParseError;
5622
5623 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5624 ComponentName activity) {
5625 super(filter);
5626 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5627 mActivity = activity;
5628 mShortActivity = activity.flattenToShortString();
5629 mParseError = null;
5630 if (set != null) {
5631 final int N = set.length;
5632 String[] myPackages = new String[N];
5633 String[] myClasses = new String[N];
5634 String[] myComponents = new String[N];
5635 for (int i=0; i<N; i++) {
5636 ComponentName cn = set[i];
5637 if (cn == null) {
5638 mSetPackages = null;
5639 mSetClasses = null;
5640 mSetComponents = null;
5641 return;
5642 }
5643 myPackages[i] = cn.getPackageName().intern();
5644 myClasses[i] = cn.getClassName().intern();
5645 myComponents[i] = cn.flattenToShortString().intern();
5646 }
5647 mSetPackages = myPackages;
5648 mSetClasses = myClasses;
5649 mSetComponents = myComponents;
5650 } else {
5651 mSetPackages = null;
5652 mSetClasses = null;
5653 mSetComponents = null;
5654 }
5655 }
5656
5657 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5658 IOException {
5659 mShortActivity = parser.getAttributeValue(null, "name");
5660 mActivity = ComponentName.unflattenFromString(mShortActivity);
5661 if (mActivity == null) {
5662 mParseError = "Bad activity name " + mShortActivity;
5663 }
5664 String matchStr = parser.getAttributeValue(null, "match");
5665 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5666 String setCountStr = parser.getAttributeValue(null, "set");
5667 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5668
5669 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5670 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5671 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5672
5673 int setPos = 0;
5674
5675 int outerDepth = parser.getDepth();
5676 int type;
5677 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5678 && (type != XmlPullParser.END_TAG
5679 || parser.getDepth() > outerDepth)) {
5680 if (type == XmlPullParser.END_TAG
5681 || type == XmlPullParser.TEXT) {
5682 continue;
5683 }
5684
5685 String tagName = parser.getName();
5686 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5687 // + parser.getDepth() + " tag=" + tagName);
5688 if (tagName.equals("set")) {
5689 String name = parser.getAttributeValue(null, "name");
5690 if (name == null) {
5691 if (mParseError == null) {
5692 mParseError = "No name in set tag in preferred activity "
5693 + mShortActivity;
5694 }
5695 } else if (setPos >= setCount) {
5696 if (mParseError == null) {
5697 mParseError = "Too many set tags in preferred activity "
5698 + mShortActivity;
5699 }
5700 } else {
5701 ComponentName cn = ComponentName.unflattenFromString(name);
5702 if (cn == null) {
5703 if (mParseError == null) {
5704 mParseError = "Bad set name " + name + " in preferred activity "
5705 + mShortActivity;
5706 }
5707 } else {
5708 myPackages[setPos] = cn.getPackageName();
5709 myClasses[setPos] = cn.getClassName();
5710 myComponents[setPos] = name;
5711 setPos++;
5712 }
5713 }
5714 XmlUtils.skipCurrentTag(parser);
5715 } else if (tagName.equals("filter")) {
5716 //Log.i(TAG, "Starting to parse filter...");
5717 readFromXml(parser);
5718 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5719 // + parser.getDepth() + " tag=" + parser.getName());
5720 } else {
5721 reportSettingsProblem(Log.WARN,
5722 "Unknown element under <preferred-activities>: "
5723 + parser.getName());
5724 XmlUtils.skipCurrentTag(parser);
5725 }
5726 }
5727
5728 if (setPos != setCount) {
5729 if (mParseError == null) {
5730 mParseError = "Not enough set tags (expected " + setCount
5731 + " but found " + setPos + ") in " + mShortActivity;
5732 }
5733 }
5734
5735 mSetPackages = myPackages;
5736 mSetClasses = myClasses;
5737 mSetComponents = myComponents;
5738 }
5739
5740 public void writeToXml(XmlSerializer serializer) throws IOException {
5741 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5742 serializer.attribute(null, "name", mShortActivity);
5743 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5744 serializer.attribute(null, "set", Integer.toString(NS));
5745 for (int s=0; s<NS; s++) {
5746 serializer.startTag(null, "set");
5747 serializer.attribute(null, "name", mSetComponents[s]);
5748 serializer.endTag(null, "set");
5749 }
5750 serializer.startTag(null, "filter");
5751 super.writeToXml(serializer);
5752 serializer.endTag(null, "filter");
5753 }
5754
5755 boolean sameSet(List<ResolveInfo> query, int priority) {
5756 if (mSetPackages == null) return false;
5757 final int NQ = query.size();
5758 final int NS = mSetPackages.length;
5759 int numMatch = 0;
5760 for (int i=0; i<NQ; i++) {
5761 ResolveInfo ri = query.get(i);
5762 if (ri.priority != priority) continue;
5763 ActivityInfo ai = ri.activityInfo;
5764 boolean good = false;
5765 for (int j=0; j<NS; j++) {
5766 if (mSetPackages[j].equals(ai.packageName)
5767 && mSetClasses[j].equals(ai.name)) {
5768 numMatch++;
5769 good = true;
5770 break;
5771 }
5772 }
5773 if (!good) return false;
5774 }
5775 return numMatch == NS;
5776 }
5777 }
5778
5779 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005780 int pkgFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781
5782 HashSet<String> grantedPermissions = new HashSet<String>();
5783 int[] gids;
5784
5785 HashSet<String> loadedPermissions = new HashSet<String>();
5786
5787 GrantedPermissions(int pkgFlags) {
5788 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5789 }
5790 }
5791
5792 /**
5793 * Settings base class for pending and resolved classes.
5794 */
5795 static class PackageSettingBase extends GrantedPermissions {
5796 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005797 File codePath;
5798 String codePathString;
5799 File resourcePath;
5800 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 private long timeStamp;
5802 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005803 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005804
5805 PackageSignatures signatures = new PackageSignatures();
5806
5807 boolean permissionsFixed;
5808
5809 /* Explicitly disabled components */
5810 HashSet<String> disabledComponents = new HashSet<String>(0);
5811 /* Explicitly enabled components */
5812 HashSet<String> enabledComponents = new HashSet<String>(0);
5813 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5814 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005815
5816 /* package name of the app that installed this package */
5817 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818
5819 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005820 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 super(pkgFlags);
5822 this.name = name;
5823 this.codePath = codePath;
5824 this.codePathString = codePath.toString();
5825 this.resourcePath = resourcePath;
5826 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005827 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 }
5829
Jacek Surazski65e13172009-04-28 15:26:38 +02005830 public void setInstallerPackageName(String packageName) {
5831 installerPackageName = packageName;
5832 }
5833
5834 String getInstallerPackageName() {
5835 return installerPackageName;
5836 }
5837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 public void setInstallStatus(int newStatus) {
5839 installStatus = newStatus;
5840 }
5841
5842 public int getInstallStatus() {
5843 return installStatus;
5844 }
5845
5846 public void setTimeStamp(long newStamp) {
5847 if (newStamp != timeStamp) {
5848 timeStamp = newStamp;
5849 timeStampString = Long.toString(newStamp);
5850 }
5851 }
5852
5853 public void setTimeStamp(long newStamp, String newStampStr) {
5854 timeStamp = newStamp;
5855 timeStampString = newStampStr;
5856 }
5857
5858 public long getTimeStamp() {
5859 return timeStamp;
5860 }
5861
5862 public String getTimeStampStr() {
5863 return timeStampString;
5864 }
5865
5866 public void copyFrom(PackageSettingBase base) {
5867 grantedPermissions = base.grantedPermissions;
5868 gids = base.gids;
5869 loadedPermissions = base.loadedPermissions;
5870
5871 timeStamp = base.timeStamp;
5872 timeStampString = base.timeStampString;
5873 signatures = base.signatures;
5874 permissionsFixed = base.permissionsFixed;
5875 disabledComponents = base.disabledComponents;
5876 enabledComponents = base.enabledComponents;
5877 enabled = base.enabled;
5878 installStatus = base.installStatus;
5879 }
5880
5881 void enableComponentLP(String componentClassName) {
5882 disabledComponents.remove(componentClassName);
5883 enabledComponents.add(componentClassName);
5884 }
5885
5886 void disableComponentLP(String componentClassName) {
5887 enabledComponents.remove(componentClassName);
5888 disabledComponents.add(componentClassName);
5889 }
5890
5891 void restoreComponentLP(String componentClassName) {
5892 enabledComponents.remove(componentClassName);
5893 disabledComponents.remove(componentClassName);
5894 }
5895
5896 int currentEnabledStateLP(String componentName) {
5897 if (enabledComponents.contains(componentName)) {
5898 return COMPONENT_ENABLED_STATE_ENABLED;
5899 } else if (disabledComponents.contains(componentName)) {
5900 return COMPONENT_ENABLED_STATE_DISABLED;
5901 } else {
5902 return COMPONENT_ENABLED_STATE_DEFAULT;
5903 }
5904 }
5905 }
5906
5907 /**
5908 * Settings data for a particular package we know about.
5909 */
5910 static final class PackageSetting extends PackageSettingBase {
5911 int userId;
5912 PackageParser.Package pkg;
5913 SharedUserSetting sharedUser;
5914
5915 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005916 int pVersionCode, int pkgFlags) {
5917 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 }
5919
5920 @Override
5921 public String toString() {
5922 return "PackageSetting{"
5923 + Integer.toHexString(System.identityHashCode(this))
5924 + " " + name + "/" + userId + "}";
5925 }
5926 }
5927
5928 /**
5929 * Settings data for a particular shared user ID we know about.
5930 */
5931 static final class SharedUserSetting extends GrantedPermissions {
5932 final String name;
5933 int userId;
5934 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5935 final PackageSignatures signatures = new PackageSignatures();
5936
5937 SharedUserSetting(String _name, int _pkgFlags) {
5938 super(_pkgFlags);
5939 name = _name;
5940 }
5941
5942 @Override
5943 public String toString() {
5944 return "SharedUserSetting{"
5945 + Integer.toHexString(System.identityHashCode(this))
5946 + " " + name + "/" + userId + "}";
5947 }
5948 }
5949
5950 /**
5951 * Holds information about dynamic settings.
5952 */
5953 private static final class Settings {
5954 private final File mSettingsFilename;
5955 private final File mBackupSettingsFilename;
5956 private final HashMap<String, PackageSetting> mPackages =
5957 new HashMap<String, PackageSetting>();
5958 // The user's preferred packages/applications, in order of preference.
5959 // First is the most preferred.
5960 private final ArrayList<PackageSetting> mPreferredPackages =
5961 new ArrayList<PackageSetting>();
5962 // List of replaced system applications
5963 final HashMap<String, PackageSetting> mDisabledSysPackages =
5964 new HashMap<String, PackageSetting>();
5965
5966 // The user's preferred activities associated with particular intent
5967 // filters.
5968 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5969 new IntentResolver<PreferredActivity, PreferredActivity>() {
5970 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005971 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005973 out.print(prefix); out.print(
5974 Integer.toHexString(System.identityHashCode(filter)));
5975 out.print(' ');
5976 out.print(filter.mActivity.flattenToShortString());
5977 out.print(" match=0x");
5978 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005980 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005982 out.print(prefix); out.print(" ");
5983 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 }
5985 }
5986 }
5987 };
5988 private final HashMap<String, SharedUserSetting> mSharedUsers =
5989 new HashMap<String, SharedUserSetting>();
5990 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5991 private final SparseArray<Object> mOtherUserIds =
5992 new SparseArray<Object>();
5993
5994 // For reading/writing settings file.
5995 private final ArrayList<Signature> mPastSignatures =
5996 new ArrayList<Signature>();
5997
5998 // Mapping from permission names to info about them.
5999 final HashMap<String, BasePermission> mPermissions =
6000 new HashMap<String, BasePermission>();
6001
6002 // Mapping from permission tree names to info about them.
6003 final HashMap<String, BasePermission> mPermissionTrees =
6004 new HashMap<String, BasePermission>();
6005
6006 private final ArrayList<String> mPendingPreferredPackages
6007 = new ArrayList<String>();
6008
6009 private final StringBuilder mReadMessages = new StringBuilder();
6010
6011 private static final class PendingPackage extends PackageSettingBase {
6012 final int sharedId;
6013
6014 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006015 int sharedId, int pVersionCode, int pkgFlags) {
6016 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 this.sharedId = sharedId;
6018 }
6019 }
6020 private final ArrayList<PendingPackage> mPendingPackages
6021 = new ArrayList<PendingPackage>();
6022
6023 Settings() {
6024 File dataDir = Environment.getDataDirectory();
6025 File systemDir = new File(dataDir, "system");
6026 systemDir.mkdirs();
6027 FileUtils.setPermissions(systemDir.toString(),
6028 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6029 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6030 -1, -1);
6031 mSettingsFilename = new File(systemDir, "packages.xml");
6032 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6033 }
6034
6035 PackageSetting getPackageLP(PackageParser.Package pkg,
6036 SharedUserSetting sharedUser, File codePath, File resourcePath,
6037 int pkgFlags, boolean create, boolean add) {
6038 final String name = pkg.packageName;
6039 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006040 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 return p;
6042 }
6043
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006044 PackageSetting peekPackageLP(String name) {
6045 return mPackages.get(name);
6046 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 PackageSetting p = mPackages.get(name);
6048 if (p != null && p.codePath.getPath().equals(codePath)) {
6049 return p;
6050 }
6051 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006052 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 }
6054
6055 void setInstallStatus(String pkgName, int status) {
6056 PackageSetting p = mPackages.get(pkgName);
6057 if(p != null) {
6058 if(p.getInstallStatus() != status) {
6059 p.setInstallStatus(status);
6060 }
6061 }
6062 }
6063
Jacek Surazski65e13172009-04-28 15:26:38 +02006064 void setInstallerPackageName(String pkgName,
6065 String installerPkgName) {
6066 PackageSetting p = mPackages.get(pkgName);
6067 if(p != null) {
6068 p.setInstallerPackageName(installerPkgName);
6069 }
6070 }
6071
6072 String getInstallerPackageName(String pkgName) {
6073 PackageSetting p = mPackages.get(pkgName);
6074 return (p == null) ? null : p.getInstallerPackageName();
6075 }
6076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 int getInstallStatus(String pkgName) {
6078 PackageSetting p = mPackages.get(pkgName);
6079 if(p != null) {
6080 return p.getInstallStatus();
6081 }
6082 return -1;
6083 }
6084
6085 SharedUserSetting getSharedUserLP(String name,
6086 int pkgFlags, boolean create) {
6087 SharedUserSetting s = mSharedUsers.get(name);
6088 if (s == null) {
6089 if (!create) {
6090 return null;
6091 }
6092 s = new SharedUserSetting(name, pkgFlags);
6093 if (MULTIPLE_APPLICATION_UIDS) {
6094 s.userId = newUserIdLP(s);
6095 } else {
6096 s.userId = FIRST_APPLICATION_UID;
6097 }
6098 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6099 // < 0 means we couldn't assign a userid; fall out and return
6100 // s, which is currently null
6101 if (s.userId >= 0) {
6102 mSharedUsers.put(name, s);
6103 }
6104 }
6105
6106 return s;
6107 }
6108
6109 int disableSystemPackageLP(String name) {
6110 PackageSetting p = mPackages.get(name);
6111 if(p == null) {
6112 Log.w(TAG, "Package:"+name+" is not an installed package");
6113 return -1;
6114 }
6115 PackageSetting dp = mDisabledSysPackages.get(name);
6116 // always make sure the system package code and resource paths dont change
6117 if(dp == null) {
6118 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6119 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6120 }
6121 mDisabledSysPackages.put(name, p);
6122 }
6123 return removePackageLP(name);
6124 }
6125
6126 PackageSetting enableSystemPackageLP(String name) {
6127 PackageSetting p = mDisabledSysPackages.get(name);
6128 if(p == null) {
6129 Log.w(TAG, "Package:"+name+" is not disabled");
6130 return null;
6131 }
6132 // Reset flag in ApplicationInfo object
6133 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6134 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6135 }
6136 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006137 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006138 mDisabledSysPackages.remove(name);
6139 return ret;
6140 }
6141
6142 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006143 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006144 PackageSetting p = mPackages.get(name);
6145 if (p != null) {
6146 if (p.userId == uid) {
6147 return p;
6148 }
6149 reportSettingsProblem(Log.ERROR,
6150 "Adding duplicate package, keeping first: " + name);
6151 return null;
6152 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006153 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006154 p.userId = uid;
6155 if (addUserIdLP(uid, p, name)) {
6156 mPackages.put(name, p);
6157 return p;
6158 }
6159 return null;
6160 }
6161
6162 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6163 SharedUserSetting s = mSharedUsers.get(name);
6164 if (s != null) {
6165 if (s.userId == uid) {
6166 return s;
6167 }
6168 reportSettingsProblem(Log.ERROR,
6169 "Adding duplicate shared user, keeping first: " + name);
6170 return null;
6171 }
6172 s = new SharedUserSetting(name, pkgFlags);
6173 s.userId = uid;
6174 if (addUserIdLP(uid, s, name)) {
6175 mSharedUsers.put(name, s);
6176 return s;
6177 }
6178 return null;
6179 }
6180
6181 private PackageSetting getPackageLP(String name,
6182 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006183 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006184 PackageSetting p = mPackages.get(name);
6185 if (p != null) {
6186 if (!p.codePath.equals(codePath)) {
6187 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006188 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006189 // This is an updated system app with versions in both system
6190 // and data partition. Just let the most recent version
6191 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006192 Log.w(TAG, "Trying to update system app code path from " +
6193 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006194 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006195 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006196 reportSettingsProblem(Log.WARN,
6197 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006198 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006199 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006200 }
6201 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 reportSettingsProblem(Log.WARN,
6203 "Package " + name + " shared user changed from "
6204 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6205 + " to "
6206 + (sharedUser != null ? sharedUser.name : "<nothing>")
6207 + "; replacing with new");
6208 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006209 } else {
6210 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6211 // If what we are scanning is a system package, then
6212 // make it so, regardless of whether it was previously
6213 // installed only in the data partition.
6214 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006216 }
6217 }
6218 if (p == null) {
6219 // Create a new PackageSettings entry. this can end up here because
6220 // of code path mismatch or user id mismatch of an updated system partition
6221 if (!create) {
6222 return null;
6223 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006224 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006225 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006226 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 if (sharedUser != null) {
6228 p.userId = sharedUser.userId;
6229 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006230 // Clone the setting here for disabled system packages
6231 PackageSetting dis = mDisabledSysPackages.get(name);
6232 if (dis != null) {
6233 // For disabled packages a new setting is created
6234 // from the existing user id. This still has to be
6235 // added to list of user id's
6236 // Copy signatures from previous setting
6237 if (dis.signatures.mSignatures != null) {
6238 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6239 }
6240 p.userId = dis.userId;
6241 // Clone permissions
6242 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6243 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6244 // Clone component info
6245 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6246 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6247 // Add new setting to list of user ids
6248 addUserIdLP(p.userId, p, name);
6249 } else {
6250 // Assign new user id
6251 p.userId = newUserIdLP(p);
6252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 } else {
6254 p.userId = FIRST_APPLICATION_UID;
6255 }
6256 if (p.userId < 0) {
6257 reportSettingsProblem(Log.WARN,
6258 "Package " + name + " could not be assigned a valid uid");
6259 return null;
6260 }
6261 if (add) {
6262 // Finish adding new package by adding it and updating shared
6263 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006264 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 }
6266 }
6267 return p;
6268 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006269
6270 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6271 File codePath, File resourcePath) {
6272 p.pkg = pkg;
6273 // Update code path if needed
6274 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6275 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006276 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006277 p.codePath = codePath;
6278 p.codePathString = codePath.toString();
6279 }
6280 //Update resource path if needed
6281 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6282 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006283 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006284 p.resourcePath = resourcePath;
6285 p.resourcePathString = resourcePath.toString();
6286 }
6287 // Update version code if needed
6288 if (pkg.mVersionCode != p.versionCode) {
6289 p.versionCode = pkg.mVersionCode;
6290 }
6291 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6292 }
6293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 // Utility method that adds a PackageSetting to mPackages and
6295 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006296 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 SharedUserSetting sharedUser) {
6298 mPackages.put(name, p);
6299 if (sharedUser != null) {
6300 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6301 reportSettingsProblem(Log.ERROR,
6302 "Package " + p.name + " was user "
6303 + p.sharedUser + " but is now " + sharedUser
6304 + "; I am not changing its files so it will probably fail!");
6305 p.sharedUser.packages.remove(p);
6306 } else if (p.userId != sharedUser.userId) {
6307 reportSettingsProblem(Log.ERROR,
6308 "Package " + p.name + " was user id " + p.userId
6309 + " but is now user " + sharedUser
6310 + " with id " + sharedUser.userId
6311 + "; I am not changing its files so it will probably fail!");
6312 }
6313
6314 sharedUser.packages.add(p);
6315 p.sharedUser = sharedUser;
6316 p.userId = sharedUser.userId;
6317 }
6318 }
6319
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006320 /*
6321 * Update the shared user setting when a package using
6322 * specifying the shared user id is removed. The gids
6323 * associated with each permission of the deleted package
6324 * are removed from the shared user's gid list only if its
6325 * not in use by other permissions of packages in the
6326 * shared user setting.
6327 */
6328 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6330 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6331 return;
6332 }
6333 // No sharedUserId
6334 if (deletedPs.sharedUser == null) {
6335 return;
6336 }
6337 SharedUserSetting sus = deletedPs.sharedUser;
6338 // Update permissions
6339 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6340 boolean used = false;
6341 if (!sus.grantedPermissions.contains (eachPerm)) {
6342 continue;
6343 }
6344 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapub97b8f82009-06-19 15:09:18 -07006345 if (pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 used = true;
6347 break;
6348 }
6349 }
6350 if (!used) {
6351 // can safely delete this permission from list
6352 sus.grantedPermissions.remove(eachPerm);
6353 sus.loadedPermissions.remove(eachPerm);
6354 }
6355 }
6356 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006357 int newGids[] = globalGids;
6358 for (String eachPerm : sus.grantedPermissions) {
6359 BasePermission bp = mPermissions.get(eachPerm);
6360 newGids = appendInts(newGids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 }
6362 sus.gids = newGids;
6363 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 private int removePackageLP(String name) {
6366 PackageSetting p = mPackages.get(name);
6367 if (p != null) {
6368 mPackages.remove(name);
6369 if (p.sharedUser != null) {
6370 p.sharedUser.packages.remove(p);
6371 if (p.sharedUser.packages.size() == 0) {
6372 mSharedUsers.remove(p.sharedUser.name);
6373 removeUserIdLP(p.sharedUser.userId);
6374 return p.sharedUser.userId;
6375 }
6376 } else {
6377 removeUserIdLP(p.userId);
6378 return p.userId;
6379 }
6380 }
6381 return -1;
6382 }
6383
6384 private boolean addUserIdLP(int uid, Object obj, Object name) {
6385 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6386 return false;
6387 }
6388
6389 if (uid >= FIRST_APPLICATION_UID) {
6390 int N = mUserIds.size();
6391 final int index = uid - FIRST_APPLICATION_UID;
6392 while (index >= N) {
6393 mUserIds.add(null);
6394 N++;
6395 }
6396 if (mUserIds.get(index) != null) {
6397 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006398 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 + " name=" + name);
6400 return false;
6401 }
6402 mUserIds.set(index, obj);
6403 } else {
6404 if (mOtherUserIds.get(uid) != null) {
6405 reportSettingsProblem(Log.ERROR,
6406 "Adding duplicate shared id: " + uid
6407 + " name=" + name);
6408 return false;
6409 }
6410 mOtherUserIds.put(uid, obj);
6411 }
6412 return true;
6413 }
6414
6415 public Object getUserIdLP(int uid) {
6416 if (uid >= FIRST_APPLICATION_UID) {
6417 int N = mUserIds.size();
6418 final int index = uid - FIRST_APPLICATION_UID;
6419 return index < N ? mUserIds.get(index) : null;
6420 } else {
6421 return mOtherUserIds.get(uid);
6422 }
6423 }
6424
6425 private void removeUserIdLP(int uid) {
6426 if (uid >= FIRST_APPLICATION_UID) {
6427 int N = mUserIds.size();
6428 final int index = uid - FIRST_APPLICATION_UID;
6429 if (index < N) mUserIds.set(index, null);
6430 } else {
6431 mOtherUserIds.remove(uid);
6432 }
6433 }
6434
6435 void writeLP() {
6436 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6437
6438 // Keep the old settings around until we know the new ones have
6439 // been successfully written.
6440 if (mSettingsFilename.exists()) {
6441 if (mBackupSettingsFilename.exists()) {
6442 mBackupSettingsFilename.delete();
6443 }
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006444 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6445 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6446 return;
6447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448 }
6449
6450 mPastSignatures.clear();
6451
6452 try {
6453 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6454
6455 //XmlSerializer serializer = XmlUtils.serializerInstance();
6456 XmlSerializer serializer = new FastXmlSerializer();
6457 serializer.setOutput(str, "utf-8");
6458 serializer.startDocument(null, true);
6459 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6460
6461 serializer.startTag(null, "packages");
6462
6463 serializer.startTag(null, "permission-trees");
6464 for (BasePermission bp : mPermissionTrees.values()) {
6465 writePermission(serializer, bp);
6466 }
6467 serializer.endTag(null, "permission-trees");
6468
6469 serializer.startTag(null, "permissions");
6470 for (BasePermission bp : mPermissions.values()) {
6471 writePermission(serializer, bp);
6472 }
6473 serializer.endTag(null, "permissions");
6474
6475 for (PackageSetting pkg : mPackages.values()) {
6476 writePackage(serializer, pkg);
6477 }
6478
6479 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6480 writeDisabledSysPackage(serializer, pkg);
6481 }
6482
6483 serializer.startTag(null, "preferred-packages");
6484 int N = mPreferredPackages.size();
6485 for (int i=0; i<N; i++) {
6486 PackageSetting pkg = mPreferredPackages.get(i);
6487 serializer.startTag(null, "item");
6488 serializer.attribute(null, "name", pkg.name);
6489 serializer.endTag(null, "item");
6490 }
6491 serializer.endTag(null, "preferred-packages");
6492
6493 serializer.startTag(null, "preferred-activities");
6494 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6495 serializer.startTag(null, "item");
6496 pa.writeToXml(serializer);
6497 serializer.endTag(null, "item");
6498 }
6499 serializer.endTag(null, "preferred-activities");
6500
6501 for (SharedUserSetting usr : mSharedUsers.values()) {
6502 serializer.startTag(null, "shared-user");
6503 serializer.attribute(null, "name", usr.name);
6504 serializer.attribute(null, "userId",
6505 Integer.toString(usr.userId));
6506 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6507 serializer.startTag(null, "perms");
6508 for (String name : usr.grantedPermissions) {
6509 serializer.startTag(null, "item");
6510 serializer.attribute(null, "name", name);
6511 serializer.endTag(null, "item");
6512 }
6513 serializer.endTag(null, "perms");
6514 serializer.endTag(null, "shared-user");
6515 }
6516
6517 serializer.endTag(null, "packages");
6518
6519 serializer.endDocument();
6520
6521 str.flush();
6522 str.close();
6523
6524 // New settings successfully written, old ones are no longer
6525 // needed.
6526 mBackupSettingsFilename.delete();
6527 FileUtils.setPermissions(mSettingsFilename.toString(),
6528 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6529 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6530 |FileUtils.S_IROTH,
6531 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006532 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533
6534 } catch(XmlPullParserException e) {
6535 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 } catch(java.io.IOException e) {
6537 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006538 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006539 // Clean up partially written file
6540 if (mSettingsFilename.exists()) {
6541 if (!mSettingsFilename.delete()) {
6542 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6543 }
6544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 //Debug.stopMethodTracing();
6546 }
6547
6548 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
6549 throws java.io.IOException {
6550 serializer.startTag(null, "updated-package");
6551 serializer.attribute(null, "name", pkg.name);
6552 serializer.attribute(null, "codePath", pkg.codePathString);
6553 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006554 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6556 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6557 }
6558 if (pkg.sharedUser == null) {
6559 serializer.attribute(null, "userId",
6560 Integer.toString(pkg.userId));
6561 } else {
6562 serializer.attribute(null, "sharedUserId",
6563 Integer.toString(pkg.userId));
6564 }
6565 serializer.startTag(null, "perms");
6566 if (pkg.sharedUser == null) {
6567 // If this is a shared user, the permissions will
6568 // be written there. We still need to write an
6569 // empty permissions list so permissionsFixed will
6570 // be set.
6571 for (final String name : pkg.grantedPermissions) {
6572 BasePermission bp = mPermissions.get(name);
6573 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6574 // We only need to write signature or system permissions but this wont
6575 // match the semantics of grantedPermissions. So write all permissions.
6576 serializer.startTag(null, "item");
6577 serializer.attribute(null, "name", name);
6578 serializer.endTag(null, "item");
6579 }
6580 }
6581 }
6582 serializer.endTag(null, "perms");
6583 serializer.endTag(null, "updated-package");
6584 }
6585
6586 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6587 throws java.io.IOException {
6588 serializer.startTag(null, "package");
6589 serializer.attribute(null, "name", pkg.name);
6590 serializer.attribute(null, "codePath", pkg.codePathString);
6591 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6592 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6593 }
6594 serializer.attribute(null, "system",
6595 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6596 ? "true" : "false");
6597 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006598 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 if (pkg.sharedUser == null) {
6600 serializer.attribute(null, "userId",
6601 Integer.toString(pkg.userId));
6602 } else {
6603 serializer.attribute(null, "sharedUserId",
6604 Integer.toString(pkg.userId));
6605 }
6606 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6607 serializer.attribute(null, "enabled",
6608 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6609 ? "true" : "false");
6610 }
6611 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6612 serializer.attribute(null, "installStatus", "false");
6613 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006614 if (pkg.installerPackageName != null) {
6615 serializer.attribute(null, "installer", pkg.installerPackageName);
6616 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006617 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6618 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6619 serializer.startTag(null, "perms");
6620 if (pkg.sharedUser == null) {
6621 // If this is a shared user, the permissions will
6622 // be written there. We still need to write an
6623 // empty permissions list so permissionsFixed will
6624 // be set.
6625 for (final String name : pkg.grantedPermissions) {
6626 serializer.startTag(null, "item");
6627 serializer.attribute(null, "name", name);
6628 serializer.endTag(null, "item");
6629 }
6630 }
6631 serializer.endTag(null, "perms");
6632 }
6633 if (pkg.disabledComponents.size() > 0) {
6634 serializer.startTag(null, "disabled-components");
6635 for (final String name : pkg.disabledComponents) {
6636 serializer.startTag(null, "item");
6637 serializer.attribute(null, "name", name);
6638 serializer.endTag(null, "item");
6639 }
6640 serializer.endTag(null, "disabled-components");
6641 }
6642 if (pkg.enabledComponents.size() > 0) {
6643 serializer.startTag(null, "enabled-components");
6644 for (final String name : pkg.enabledComponents) {
6645 serializer.startTag(null, "item");
6646 serializer.attribute(null, "name", name);
6647 serializer.endTag(null, "item");
6648 }
6649 serializer.endTag(null, "enabled-components");
6650 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006652 serializer.endTag(null, "package");
6653 }
6654
6655 void writePermission(XmlSerializer serializer, BasePermission bp)
6656 throws XmlPullParserException, java.io.IOException {
6657 if (bp.type != BasePermission.TYPE_BUILTIN
6658 && bp.sourcePackage != null) {
6659 serializer.startTag(null, "item");
6660 serializer.attribute(null, "name", bp.name);
6661 serializer.attribute(null, "package", bp.sourcePackage);
6662 if (DEBUG_SETTINGS) Log.v(TAG,
6663 "Writing perm: name=" + bp.name + " type=" + bp.type);
6664 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6665 PermissionInfo pi = bp.perm != null ? bp.perm.info
6666 : bp.pendingInfo;
6667 if (pi != null) {
6668 serializer.attribute(null, "type", "dynamic");
6669 if (pi.icon != 0) {
6670 serializer.attribute(null, "icon",
6671 Integer.toString(pi.icon));
6672 }
6673 if (pi.nonLocalizedLabel != null) {
6674 serializer.attribute(null, "label",
6675 pi.nonLocalizedLabel.toString());
6676 }
6677 if (pi.protectionLevel !=
6678 PermissionInfo.PROTECTION_NORMAL) {
6679 serializer.attribute(null, "protection",
6680 Integer.toString(pi.protectionLevel));
6681 }
6682 }
6683 }
6684 serializer.endTag(null, "item");
6685 }
6686 }
6687
6688 String getReadMessagesLP() {
6689 return mReadMessages.toString();
6690 }
6691
6692 ArrayList<String> getListOfIncompleteInstallPackages() {
6693 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6694 Iterator<String> its = kList.iterator();
6695 ArrayList<String> ret = new ArrayList<String>();
6696 while(its.hasNext()) {
6697 String key = its.next();
6698 PackageSetting ps = mPackages.get(key);
6699 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6700 ret.add(key);
6701 }
6702 }
6703 return ret;
6704 }
6705
6706 boolean readLP() {
6707 FileInputStream str = null;
6708 if (mBackupSettingsFilename.exists()) {
6709 try {
6710 str = new FileInputStream(mBackupSettingsFilename);
6711 mReadMessages.append("Reading from backup settings file\n");
6712 Log.i(TAG, "Reading from backup settings file!");
6713 } catch (java.io.IOException e) {
6714 // We'll try for the normal settings file.
6715 }
6716 }
6717
6718 mPastSignatures.clear();
6719
6720 try {
6721 if (str == null) {
6722 if (!mSettingsFilename.exists()) {
6723 mReadMessages.append("No settings file found\n");
6724 Log.i(TAG, "No current settings file!");
6725 return false;
6726 }
6727 str = new FileInputStream(mSettingsFilename);
6728 }
6729 XmlPullParser parser = Xml.newPullParser();
6730 parser.setInput(str, null);
6731
6732 int type;
6733 while ((type=parser.next()) != XmlPullParser.START_TAG
6734 && type != XmlPullParser.END_DOCUMENT) {
6735 ;
6736 }
6737
6738 if (type != XmlPullParser.START_TAG) {
6739 mReadMessages.append("No start tag found in settings file\n");
6740 Log.e(TAG, "No start tag found in package manager settings");
6741 return false;
6742 }
6743
6744 int outerDepth = parser.getDepth();
6745 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6746 && (type != XmlPullParser.END_TAG
6747 || parser.getDepth() > outerDepth)) {
6748 if (type == XmlPullParser.END_TAG
6749 || type == XmlPullParser.TEXT) {
6750 continue;
6751 }
6752
6753 String tagName = parser.getName();
6754 if (tagName.equals("package")) {
6755 readPackageLP(parser);
6756 } else if (tagName.equals("permissions")) {
6757 readPermissionsLP(mPermissions, parser);
6758 } else if (tagName.equals("permission-trees")) {
6759 readPermissionsLP(mPermissionTrees, parser);
6760 } else if (tagName.equals("shared-user")) {
6761 readSharedUserLP(parser);
6762 } else if (tagName.equals("preferred-packages")) {
6763 readPreferredPackagesLP(parser);
6764 } else if (tagName.equals("preferred-activities")) {
6765 readPreferredActivitiesLP(parser);
6766 } else if(tagName.equals("updated-package")) {
6767 readDisabledSysPackageLP(parser);
6768 } else {
6769 Log.w(TAG, "Unknown element under <packages>: "
6770 + parser.getName());
6771 XmlUtils.skipCurrentTag(parser);
6772 }
6773 }
6774
6775 str.close();
6776
6777 } catch(XmlPullParserException e) {
6778 mReadMessages.append("Error reading: " + e.toString());
6779 Log.e(TAG, "Error reading package manager settings", e);
6780
6781 } catch(java.io.IOException e) {
6782 mReadMessages.append("Error reading: " + e.toString());
6783 Log.e(TAG, "Error reading package manager settings", e);
6784
6785 }
6786
6787 int N = mPendingPackages.size();
6788 for (int i=0; i<N; i++) {
6789 final PendingPackage pp = mPendingPackages.get(i);
6790 Object idObj = getUserIdLP(pp.sharedId);
6791 if (idObj != null && idObj instanceof SharedUserSetting) {
6792 PackageSetting p = getPackageLP(pp.name,
6793 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006794 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 if (p == null) {
6796 Log.w(TAG, "Unable to create application package for "
6797 + pp.name);
6798 continue;
6799 }
6800 p.copyFrom(pp);
6801 } else if (idObj != null) {
6802 String msg = "Bad package setting: package " + pp.name
6803 + " has shared uid " + pp.sharedId
6804 + " that is not a shared uid\n";
6805 mReadMessages.append(msg);
6806 Log.e(TAG, msg);
6807 } else {
6808 String msg = "Bad package setting: package " + pp.name
6809 + " has shared uid " + pp.sharedId
6810 + " that is not defined\n";
6811 mReadMessages.append(msg);
6812 Log.e(TAG, msg);
6813 }
6814 }
6815 mPendingPackages.clear();
6816
6817 N = mPendingPreferredPackages.size();
6818 mPreferredPackages.clear();
6819 for (int i=0; i<N; i++) {
6820 final String name = mPendingPreferredPackages.get(i);
6821 final PackageSetting p = mPackages.get(name);
6822 if (p != null) {
6823 mPreferredPackages.add(p);
6824 } else {
6825 Log.w(TAG, "Unknown preferred package: " + name);
6826 }
6827 }
6828 mPendingPreferredPackages.clear();
6829
6830 mReadMessages.append("Read completed successfully: "
6831 + mPackages.size() + " packages, "
6832 + mSharedUsers.size() + " shared uids\n");
6833
6834 return true;
6835 }
6836
6837 private int readInt(XmlPullParser parser, String ns, String name,
6838 int defValue) {
6839 String v = parser.getAttributeValue(ns, name);
6840 try {
6841 if (v == null) {
6842 return defValue;
6843 }
6844 return Integer.parseInt(v);
6845 } catch (NumberFormatException e) {
6846 reportSettingsProblem(Log.WARN,
6847 "Error in package manager settings: attribute " +
6848 name + " has bad integer value " + v + " at "
6849 + parser.getPositionDescription());
6850 }
6851 return defValue;
6852 }
6853
6854 private void readPermissionsLP(HashMap<String, BasePermission> out,
6855 XmlPullParser parser)
6856 throws IOException, XmlPullParserException {
6857 int outerDepth = parser.getDepth();
6858 int type;
6859 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6860 && (type != XmlPullParser.END_TAG
6861 || parser.getDepth() > outerDepth)) {
6862 if (type == XmlPullParser.END_TAG
6863 || type == XmlPullParser.TEXT) {
6864 continue;
6865 }
6866
6867 String tagName = parser.getName();
6868 if (tagName.equals("item")) {
6869 String name = parser.getAttributeValue(null, "name");
6870 String sourcePackage = parser.getAttributeValue(null, "package");
6871 String ptype = parser.getAttributeValue(null, "type");
6872 if (name != null && sourcePackage != null) {
6873 boolean dynamic = "dynamic".equals(ptype);
6874 BasePermission bp = new BasePermission(name, sourcePackage,
6875 dynamic
6876 ? BasePermission.TYPE_DYNAMIC
6877 : BasePermission.TYPE_NORMAL);
6878 if (dynamic) {
6879 PermissionInfo pi = new PermissionInfo();
6880 pi.packageName = sourcePackage.intern();
6881 pi.name = name.intern();
6882 pi.icon = readInt(parser, null, "icon", 0);
6883 pi.nonLocalizedLabel = parser.getAttributeValue(
6884 null, "label");
6885 pi.protectionLevel = readInt(parser, null, "protection",
6886 PermissionInfo.PROTECTION_NORMAL);
6887 bp.pendingInfo = pi;
6888 }
6889 out.put(bp.name, bp);
6890 } else {
6891 reportSettingsProblem(Log.WARN,
6892 "Error in package manager settings: permissions has"
6893 + " no name at " + parser.getPositionDescription());
6894 }
6895 } else {
6896 reportSettingsProblem(Log.WARN,
6897 "Unknown element reading permissions: "
6898 + parser.getName() + " at "
6899 + parser.getPositionDescription());
6900 }
6901 XmlUtils.skipCurrentTag(parser);
6902 }
6903 }
6904
6905 private void readDisabledSysPackageLP(XmlPullParser parser)
6906 throws XmlPullParserException, IOException {
6907 String name = parser.getAttributeValue(null, "name");
6908 String codePathStr = parser.getAttributeValue(null, "codePath");
6909 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6910 if(resourcePathStr == null) {
6911 resourcePathStr = codePathStr;
6912 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006913 String version = parser.getAttributeValue(null, "version");
6914 int versionCode = 0;
6915 if (version != null) {
6916 try {
6917 versionCode = Integer.parseInt(version);
6918 } catch (NumberFormatException e) {
6919 }
6920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921
6922 int pkgFlags = 0;
6923 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6924 PackageSetting ps = new PackageSetting(name,
6925 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006926 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 String timeStampStr = parser.getAttributeValue(null, "ts");
6928 if (timeStampStr != null) {
6929 try {
6930 long timeStamp = Long.parseLong(timeStampStr);
6931 ps.setTimeStamp(timeStamp, timeStampStr);
6932 } catch (NumberFormatException e) {
6933 }
6934 }
6935 String idStr = parser.getAttributeValue(null, "userId");
6936 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6937 if(ps.userId <= 0) {
6938 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6939 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6940 }
6941 int outerDepth = parser.getDepth();
6942 int type;
6943 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6944 && (type != XmlPullParser.END_TAG
6945 || parser.getDepth() > outerDepth)) {
6946 if (type == XmlPullParser.END_TAG
6947 || type == XmlPullParser.TEXT) {
6948 continue;
6949 }
6950
6951 String tagName = parser.getName();
6952 if (tagName.equals("perms")) {
6953 readGrantedPermissionsLP(parser,
6954 ps.grantedPermissions);
6955 } else {
6956 reportSettingsProblem(Log.WARN,
6957 "Unknown element under <updated-package>: "
6958 + parser.getName());
6959 XmlUtils.skipCurrentTag(parser);
6960 }
6961 }
6962 mDisabledSysPackages.put(name, ps);
6963 }
6964
6965 private void readPackageLP(XmlPullParser parser)
6966 throws XmlPullParserException, IOException {
6967 String name = null;
6968 String idStr = null;
6969 String sharedIdStr = null;
6970 String codePathStr = null;
6971 String resourcePathStr = null;
6972 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02006973 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 int pkgFlags = 0;
6975 String timeStampStr;
6976 long timeStamp = 0;
6977 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006978 String version = null;
6979 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006980 try {
6981 name = parser.getAttributeValue(null, "name");
6982 idStr = parser.getAttributeValue(null, "userId");
6983 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6984 codePathStr = parser.getAttributeValue(null, "codePath");
6985 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006986 version = parser.getAttributeValue(null, "version");
6987 if (version != null) {
6988 try {
6989 versionCode = Integer.parseInt(version);
6990 } catch (NumberFormatException e) {
6991 }
6992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02006994 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006995 if (systemStr != null) {
6996 if ("true".equals(systemStr)) {
6997 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6998 }
6999 } else {
7000 // Old settings that don't specify system... just treat
7001 // them as system, good enough.
7002 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7003 }
7004 timeStampStr = parser.getAttributeValue(null, "ts");
7005 if (timeStampStr != null) {
7006 try {
7007 timeStamp = Long.parseLong(timeStampStr);
7008 } catch (NumberFormatException e) {
7009 }
7010 }
7011 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7012 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7013 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7014 if (resourcePathStr == null) {
7015 resourcePathStr = codePathStr;
7016 }
7017 if (name == null) {
7018 reportSettingsProblem(Log.WARN,
7019 "Error in package manager settings: <package> has no name at "
7020 + parser.getPositionDescription());
7021 } else if (codePathStr == null) {
7022 reportSettingsProblem(Log.WARN,
7023 "Error in package manager settings: <package> has no codePath at "
7024 + parser.getPositionDescription());
7025 } else if (userId > 0) {
7026 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007027 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007028 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7029 + ": userId=" + userId + " pkg=" + packageSetting);
7030 if (packageSetting == null) {
7031 reportSettingsProblem(Log.ERROR,
7032 "Failure adding uid " + userId
7033 + " while parsing settings at "
7034 + parser.getPositionDescription());
7035 } else {
7036 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7037 }
7038 } else if (sharedIdStr != null) {
7039 userId = sharedIdStr != null
7040 ? Integer.parseInt(sharedIdStr) : 0;
7041 if (userId > 0) {
7042 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007043 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7045 mPendingPackages.add((PendingPackage) packageSetting);
7046 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7047 + ": sharedUserId=" + userId + " pkg="
7048 + packageSetting);
7049 } else {
7050 reportSettingsProblem(Log.WARN,
7051 "Error in package manager settings: package "
7052 + name + " has bad sharedId " + sharedIdStr
7053 + " at " + parser.getPositionDescription());
7054 }
7055 } else {
7056 reportSettingsProblem(Log.WARN,
7057 "Error in package manager settings: package "
7058 + name + " has bad userId " + idStr + " at "
7059 + parser.getPositionDescription());
7060 }
7061 } catch (NumberFormatException e) {
7062 reportSettingsProblem(Log.WARN,
7063 "Error in package manager settings: package "
7064 + name + " has bad userId " + idStr + " at "
7065 + parser.getPositionDescription());
7066 }
7067 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007068 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007069 final String enabledStr = parser.getAttributeValue(null, "enabled");
7070 if (enabledStr != null) {
7071 if (enabledStr.equalsIgnoreCase("true")) {
7072 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7073 } else if (enabledStr.equalsIgnoreCase("false")) {
7074 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7075 } else if (enabledStr.equalsIgnoreCase("default")) {
7076 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7077 } else {
7078 reportSettingsProblem(Log.WARN,
7079 "Error in package manager settings: package "
7080 + name + " has bad enabled value: " + idStr
7081 + " at " + parser.getPositionDescription());
7082 }
7083 } else {
7084 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7085 }
7086 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7087 if (installStatusStr != null) {
7088 if (installStatusStr.equalsIgnoreCase("false")) {
7089 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7090 } else {
7091 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7092 }
7093 }
7094
7095 int outerDepth = parser.getDepth();
7096 int type;
7097 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7098 && (type != XmlPullParser.END_TAG
7099 || parser.getDepth() > outerDepth)) {
7100 if (type == XmlPullParser.END_TAG
7101 || type == XmlPullParser.TEXT) {
7102 continue;
7103 }
7104
7105 String tagName = parser.getName();
7106 if (tagName.equals("disabled-components")) {
7107 readDisabledComponentsLP(packageSetting, parser);
7108 } else if (tagName.equals("enabled-components")) {
7109 readEnabledComponentsLP(packageSetting, parser);
7110 } else if (tagName.equals("sigs")) {
7111 packageSetting.signatures.readXml(parser, mPastSignatures);
7112 } else if (tagName.equals("perms")) {
7113 readGrantedPermissionsLP(parser,
7114 packageSetting.loadedPermissions);
7115 packageSetting.permissionsFixed = true;
7116 } else {
7117 reportSettingsProblem(Log.WARN,
7118 "Unknown element under <package>: "
7119 + parser.getName());
7120 XmlUtils.skipCurrentTag(parser);
7121 }
7122 }
7123 } else {
7124 XmlUtils.skipCurrentTag(parser);
7125 }
7126 }
7127
7128 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7129 XmlPullParser parser)
7130 throws IOException, XmlPullParserException {
7131 int outerDepth = parser.getDepth();
7132 int type;
7133 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7134 && (type != XmlPullParser.END_TAG
7135 || parser.getDepth() > outerDepth)) {
7136 if (type == XmlPullParser.END_TAG
7137 || type == XmlPullParser.TEXT) {
7138 continue;
7139 }
7140
7141 String tagName = parser.getName();
7142 if (tagName.equals("item")) {
7143 String name = parser.getAttributeValue(null, "name");
7144 if (name != null) {
7145 packageSetting.disabledComponents.add(name.intern());
7146 } else {
7147 reportSettingsProblem(Log.WARN,
7148 "Error in package manager settings: <disabled-components> has"
7149 + " no name at " + parser.getPositionDescription());
7150 }
7151 } else {
7152 reportSettingsProblem(Log.WARN,
7153 "Unknown element under <disabled-components>: "
7154 + parser.getName());
7155 }
7156 XmlUtils.skipCurrentTag(parser);
7157 }
7158 }
7159
7160 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7161 XmlPullParser parser)
7162 throws IOException, XmlPullParserException {
7163 int outerDepth = parser.getDepth();
7164 int type;
7165 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7166 && (type != XmlPullParser.END_TAG
7167 || parser.getDepth() > outerDepth)) {
7168 if (type == XmlPullParser.END_TAG
7169 || type == XmlPullParser.TEXT) {
7170 continue;
7171 }
7172
7173 String tagName = parser.getName();
7174 if (tagName.equals("item")) {
7175 String name = parser.getAttributeValue(null, "name");
7176 if (name != null) {
7177 packageSetting.enabledComponents.add(name.intern());
7178 } else {
7179 reportSettingsProblem(Log.WARN,
7180 "Error in package manager settings: <enabled-components> has"
7181 + " no name at " + parser.getPositionDescription());
7182 }
7183 } else {
7184 reportSettingsProblem(Log.WARN,
7185 "Unknown element under <enabled-components>: "
7186 + parser.getName());
7187 }
7188 XmlUtils.skipCurrentTag(parser);
7189 }
7190 }
7191
7192 private void readSharedUserLP(XmlPullParser parser)
7193 throws XmlPullParserException, IOException {
7194 String name = null;
7195 String idStr = null;
7196 int pkgFlags = 0;
7197 SharedUserSetting su = null;
7198 try {
7199 name = parser.getAttributeValue(null, "name");
7200 idStr = parser.getAttributeValue(null, "userId");
7201 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7202 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7203 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7204 }
7205 if (name == null) {
7206 reportSettingsProblem(Log.WARN,
7207 "Error in package manager settings: <shared-user> has no name at "
7208 + parser.getPositionDescription());
7209 } else if (userId == 0) {
7210 reportSettingsProblem(Log.WARN,
7211 "Error in package manager settings: shared-user "
7212 + name + " has bad userId " + idStr + " at "
7213 + parser.getPositionDescription());
7214 } else {
7215 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7216 reportSettingsProblem(Log.ERROR,
7217 "Occurred while parsing settings at "
7218 + parser.getPositionDescription());
7219 }
7220 }
7221 } catch (NumberFormatException e) {
7222 reportSettingsProblem(Log.WARN,
7223 "Error in package manager settings: package "
7224 + name + " has bad userId " + idStr + " at "
7225 + parser.getPositionDescription());
7226 };
7227
7228 if (su != null) {
7229 int outerDepth = parser.getDepth();
7230 int type;
7231 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7232 && (type != XmlPullParser.END_TAG
7233 || parser.getDepth() > outerDepth)) {
7234 if (type == XmlPullParser.END_TAG
7235 || type == XmlPullParser.TEXT) {
7236 continue;
7237 }
7238
7239 String tagName = parser.getName();
7240 if (tagName.equals("sigs")) {
7241 su.signatures.readXml(parser, mPastSignatures);
7242 } else if (tagName.equals("perms")) {
7243 readGrantedPermissionsLP(parser, su.loadedPermissions);
7244 } else {
7245 reportSettingsProblem(Log.WARN,
7246 "Unknown element under <shared-user>: "
7247 + parser.getName());
7248 XmlUtils.skipCurrentTag(parser);
7249 }
7250 }
7251
7252 } else {
7253 XmlUtils.skipCurrentTag(parser);
7254 }
7255 }
7256
7257 private void readGrantedPermissionsLP(XmlPullParser parser,
7258 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7259 int outerDepth = parser.getDepth();
7260 int type;
7261 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7262 && (type != XmlPullParser.END_TAG
7263 || parser.getDepth() > outerDepth)) {
7264 if (type == XmlPullParser.END_TAG
7265 || type == XmlPullParser.TEXT) {
7266 continue;
7267 }
7268
7269 String tagName = parser.getName();
7270 if (tagName.equals("item")) {
7271 String name = parser.getAttributeValue(null, "name");
7272 if (name != null) {
7273 outPerms.add(name.intern());
7274 } else {
7275 reportSettingsProblem(Log.WARN,
7276 "Error in package manager settings: <perms> has"
7277 + " no name at " + parser.getPositionDescription());
7278 }
7279 } else {
7280 reportSettingsProblem(Log.WARN,
7281 "Unknown element under <perms>: "
7282 + parser.getName());
7283 }
7284 XmlUtils.skipCurrentTag(parser);
7285 }
7286 }
7287
7288 private void readPreferredPackagesLP(XmlPullParser parser)
7289 throws XmlPullParserException, IOException {
7290 int outerDepth = parser.getDepth();
7291 int type;
7292 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7293 && (type != XmlPullParser.END_TAG
7294 || parser.getDepth() > outerDepth)) {
7295 if (type == XmlPullParser.END_TAG
7296 || type == XmlPullParser.TEXT) {
7297 continue;
7298 }
7299
7300 String tagName = parser.getName();
7301 if (tagName.equals("item")) {
7302 String name = parser.getAttributeValue(null, "name");
7303 if (name != null) {
7304 mPendingPreferredPackages.add(name);
7305 } else {
7306 reportSettingsProblem(Log.WARN,
7307 "Error in package manager settings: <preferred-package> has no name at "
7308 + parser.getPositionDescription());
7309 }
7310 } else {
7311 reportSettingsProblem(Log.WARN,
7312 "Unknown element under <preferred-packages>: "
7313 + parser.getName());
7314 }
7315 XmlUtils.skipCurrentTag(parser);
7316 }
7317 }
7318
7319 private void readPreferredActivitiesLP(XmlPullParser parser)
7320 throws XmlPullParserException, IOException {
7321 int outerDepth = parser.getDepth();
7322 int type;
7323 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7324 && (type != XmlPullParser.END_TAG
7325 || parser.getDepth() > outerDepth)) {
7326 if (type == XmlPullParser.END_TAG
7327 || type == XmlPullParser.TEXT) {
7328 continue;
7329 }
7330
7331 String tagName = parser.getName();
7332 if (tagName.equals("item")) {
7333 PreferredActivity pa = new PreferredActivity(parser);
7334 if (pa.mParseError == null) {
7335 mPreferredActivities.addFilter(pa);
7336 } else {
7337 reportSettingsProblem(Log.WARN,
7338 "Error in package manager settings: <preferred-activity> "
7339 + pa.mParseError + " at "
7340 + parser.getPositionDescription());
7341 }
7342 } else {
7343 reportSettingsProblem(Log.WARN,
7344 "Unknown element under <preferred-activities>: "
7345 + parser.getName());
7346 XmlUtils.skipCurrentTag(parser);
7347 }
7348 }
7349 }
7350
7351 // Returns -1 if we could not find an available UserId to assign
7352 private int newUserIdLP(Object obj) {
7353 // Let's be stupidly inefficient for now...
7354 final int N = mUserIds.size();
7355 for (int i=0; i<N; i++) {
7356 if (mUserIds.get(i) == null) {
7357 mUserIds.set(i, obj);
7358 return FIRST_APPLICATION_UID + i;
7359 }
7360 }
7361
7362 // None left?
7363 if (N >= MAX_APPLICATION_UIDS) {
7364 return -1;
7365 }
7366
7367 mUserIds.add(obj);
7368 return FIRST_APPLICATION_UID + N;
7369 }
7370
7371 public PackageSetting getDisabledSystemPkg(String name) {
7372 synchronized(mPackages) {
7373 PackageSetting ps = mDisabledSysPackages.get(name);
7374 return ps;
7375 }
7376 }
7377
7378 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7379 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7380 if (Config.LOGV) {
7381 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7382 + " componentName = " + componentInfo.name);
7383 Log.v(TAG, "enabledComponents: "
7384 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7385 Log.v(TAG, "disabledComponents: "
7386 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7387 }
7388 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7389 || ((componentInfo.enabled
7390 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7391 || (componentInfo.applicationInfo.enabled
7392 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7393 && !packageSettings.disabledComponents.contains(componentInfo.name))
7394 || packageSettings.enabledComponents.contains(componentInfo.name));
7395 }
7396 }
7397}