blob: a83459edaba569d05ac7bccf31053ca255d993fc [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) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700875 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
876 // The package has been uninstalled but has retained data and resources.
877 return PackageParser.generatePackageInfo(p, null, flags);
878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 final PackageSetting ps = (PackageSetting)p.mExtras;
880 if (ps == null) {
881 return null;
882 }
883 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
884 return PackageParser.generatePackageInfo(p, gp.gids, flags);
885 }
886
887 public PackageInfo getPackageInfo(String packageName, int flags) {
888 synchronized (mPackages) {
889 PackageParser.Package p = mPackages.get(packageName);
890 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700891 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 + ": " + p);
893 if (p != null) {
894 return generatePackageInfo(p, flags);
895 }
896 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
897 return generatePackageInfoFromSettingsLP(packageName, flags);
898 }
899 }
900 return null;
901 }
902
903 public int getPackageUid(String packageName) {
904 synchronized (mPackages) {
905 PackageParser.Package p = mPackages.get(packageName);
906 if(p != null) {
907 return p.applicationInfo.uid;
908 }
909 PackageSetting ps = mSettings.mPackages.get(packageName);
910 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
911 return -1;
912 }
913 p = ps.pkg;
914 return p != null ? p.applicationInfo.uid : -1;
915 }
916 }
917
918 public int[] getPackageGids(String packageName) {
919 synchronized (mPackages) {
920 PackageParser.Package p = mPackages.get(packageName);
921 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700922 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 + ": " + p);
924 if (p != null) {
925 final PackageSetting ps = (PackageSetting)p.mExtras;
926 final SharedUserSetting suid = ps.sharedUser;
927 return suid != null ? suid.gids : ps.gids;
928 }
929 }
930 // stupid thing to indicate an error.
931 return new int[0];
932 }
933
934 public PermissionInfo getPermissionInfo(String name, int flags) {
935 synchronized (mPackages) {
936 final BasePermission p = mSettings.mPermissions.get(name);
937 if (p != null && p.perm != null) {
938 return PackageParser.generatePermissionInfo(p.perm, flags);
939 }
940 return null;
941 }
942 }
943
944 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
945 synchronized (mPackages) {
946 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
947 for (BasePermission p : mSettings.mPermissions.values()) {
948 if (group == null) {
949 if (p.perm.info.group == null) {
950 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
951 }
952 } else {
953 if (group.equals(p.perm.info.group)) {
954 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
955 }
956 }
957 }
958
959 if (out.size() > 0) {
960 return out;
961 }
962 return mPermissionGroups.containsKey(group) ? out : null;
963 }
964 }
965
966 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
967 synchronized (mPackages) {
968 return PackageParser.generatePermissionGroupInfo(
969 mPermissionGroups.get(name), flags);
970 }
971 }
972
973 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
974 synchronized (mPackages) {
975 final int N = mPermissionGroups.size();
976 ArrayList<PermissionGroupInfo> out
977 = new ArrayList<PermissionGroupInfo>(N);
978 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
979 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
980 }
981 return out;
982 }
983 }
984
985 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
986 PackageSetting ps = mSettings.mPackages.get(packageName);
987 if(ps != null) {
988 if(ps.pkg == null) {
989 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
990 if(pInfo != null) {
991 return pInfo.applicationInfo;
992 }
993 return null;
994 }
995 return PackageParser.generateApplicationInfo(ps.pkg, flags);
996 }
997 return null;
998 }
999
1000 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1001 PackageSetting ps = mSettings.mPackages.get(packageName);
1002 if(ps != null) {
1003 if(ps.pkg == null) {
1004 ps.pkg = new PackageParser.Package(packageName);
1005 ps.pkg.applicationInfo.packageName = packageName;
1006 }
1007 return generatePackageInfo(ps.pkg, flags);
1008 }
1009 return null;
1010 }
1011
1012 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1013 synchronized (mPackages) {
1014 PackageParser.Package p = mPackages.get(packageName);
1015 if (Config.LOGV) Log.v(
1016 TAG, "getApplicationInfo " + packageName
1017 + ": " + p);
1018 if (p != null) {
1019 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001020 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 }
1022 if ("android".equals(packageName)||"system".equals(packageName)) {
1023 return mAndroidApplication;
1024 }
1025 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1026 return generateApplicationInfoFromSettingsLP(packageName, flags);
1027 }
1028 }
1029 return null;
1030 }
1031
1032
1033 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1034 mContext.enforceCallingOrSelfPermission(
1035 android.Manifest.permission.CLEAR_APP_CACHE, null);
1036 // Queue up an async operation since clearing cache may take a little while.
1037 mHandler.post(new Runnable() {
1038 public void run() {
1039 mHandler.removeCallbacks(this);
1040 int retCode = -1;
1041 if (mInstaller != null) {
1042 retCode = mInstaller.freeCache(freeStorageSize);
1043 if (retCode < 0) {
1044 Log.w(TAG, "Couldn't clear application caches");
1045 }
1046 } //end if mInstaller
1047 if (observer != null) {
1048 try {
1049 observer.onRemoveCompleted(null, (retCode >= 0));
1050 } catch (RemoteException e) {
1051 Log.w(TAG, "RemoveException when invoking call back");
1052 }
1053 }
1054 }
1055 });
1056 }
1057
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001058 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001059 mContext.enforceCallingOrSelfPermission(
1060 android.Manifest.permission.CLEAR_APP_CACHE, null);
1061 // Queue up an async operation since clearing cache may take a little while.
1062 mHandler.post(new Runnable() {
1063 public void run() {
1064 mHandler.removeCallbacks(this);
1065 int retCode = -1;
1066 if (mInstaller != null) {
1067 retCode = mInstaller.freeCache(freeStorageSize);
1068 if (retCode < 0) {
1069 Log.w(TAG, "Couldn't clear application caches");
1070 }
1071 }
1072 if(pi != null) {
1073 try {
1074 // Callback via pending intent
1075 int code = (retCode >= 0) ? 1 : 0;
1076 pi.sendIntent(null, code, null,
1077 null, null);
1078 } catch (SendIntentException e1) {
1079 Log.i(TAG, "Failed to send pending intent");
1080 }
1081 }
1082 }
1083 });
1084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085
1086 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1087 synchronized (mPackages) {
1088 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001089
1090 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001092 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 }
1094 if (mResolveComponentName.equals(component)) {
1095 return mResolveActivity;
1096 }
1097 }
1098 return null;
1099 }
1100
1101 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1102 synchronized (mPackages) {
1103 PackageParser.Activity a = mReceivers.mActivities.get(component);
1104 if (Config.LOGV) Log.v(
1105 TAG, "getReceiverInfo " + component + ": " + a);
1106 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1107 return PackageParser.generateActivityInfo(a, flags);
1108 }
1109 }
1110 return null;
1111 }
1112
1113 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1114 synchronized (mPackages) {
1115 PackageParser.Service s = mServices.mServices.get(component);
1116 if (Config.LOGV) Log.v(
1117 TAG, "getServiceInfo " + component + ": " + s);
1118 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1119 return PackageParser.generateServiceInfo(s, flags);
1120 }
1121 }
1122 return null;
1123 }
1124
1125 public String[] getSystemSharedLibraryNames() {
1126 Set<String> libSet;
1127 synchronized (mPackages) {
1128 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001129 int size = libSet.size();
1130 if (size > 0) {
1131 String[] libs = new String[size];
1132 libSet.toArray(libs);
1133 return libs;
1134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001136 return null;
1137 }
1138
1139 public FeatureInfo[] getSystemAvailableFeatures() {
1140 Collection<FeatureInfo> featSet;
1141 synchronized (mPackages) {
1142 featSet = mAvailableFeatures.values();
1143 int size = featSet.size();
1144 if (size > 0) {
1145 FeatureInfo[] features = new FeatureInfo[size+1];
1146 featSet.toArray(features);
1147 FeatureInfo fi = new FeatureInfo();
1148 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1149 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1150 features[size] = fi;
1151 return features;
1152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 }
1154 return null;
1155 }
1156
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001157 public boolean hasSystemFeature(String name) {
1158 synchronized (mPackages) {
1159 return mAvailableFeatures.containsKey(name);
1160 }
1161 }
1162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 public int checkPermission(String permName, String pkgName) {
1164 synchronized (mPackages) {
1165 PackageParser.Package p = mPackages.get(pkgName);
1166 if (p != null && p.mExtras != null) {
1167 PackageSetting ps = (PackageSetting)p.mExtras;
1168 if (ps.sharedUser != null) {
1169 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1170 return PackageManager.PERMISSION_GRANTED;
1171 }
1172 } else if (ps.grantedPermissions.contains(permName)) {
1173 return PackageManager.PERMISSION_GRANTED;
1174 }
1175 }
1176 }
1177 return PackageManager.PERMISSION_DENIED;
1178 }
1179
1180 public int checkUidPermission(String permName, int uid) {
1181 synchronized (mPackages) {
1182 Object obj = mSettings.getUserIdLP(uid);
1183 if (obj != null) {
1184 if (obj instanceof SharedUserSetting) {
1185 SharedUserSetting sus = (SharedUserSetting)obj;
1186 if (sus.grantedPermissions.contains(permName)) {
1187 return PackageManager.PERMISSION_GRANTED;
1188 }
1189 } else if (obj instanceof PackageSetting) {
1190 PackageSetting ps = (PackageSetting)obj;
1191 if (ps.grantedPermissions.contains(permName)) {
1192 return PackageManager.PERMISSION_GRANTED;
1193 }
1194 }
1195 } else {
1196 HashSet<String> perms = mSystemPermissions.get(uid);
1197 if (perms != null && perms.contains(permName)) {
1198 return PackageManager.PERMISSION_GRANTED;
1199 }
1200 }
1201 }
1202 return PackageManager.PERMISSION_DENIED;
1203 }
1204
1205 private BasePermission findPermissionTreeLP(String permName) {
1206 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1207 if (permName.startsWith(bp.name) &&
1208 permName.length() > bp.name.length() &&
1209 permName.charAt(bp.name.length()) == '.') {
1210 return bp;
1211 }
1212 }
1213 return null;
1214 }
1215
1216 private BasePermission checkPermissionTreeLP(String permName) {
1217 if (permName != null) {
1218 BasePermission bp = findPermissionTreeLP(permName);
1219 if (bp != null) {
1220 if (bp.uid == Binder.getCallingUid()) {
1221 return bp;
1222 }
1223 throw new SecurityException("Calling uid "
1224 + Binder.getCallingUid()
1225 + " is not allowed to add to permission tree "
1226 + bp.name + " owned by uid " + bp.uid);
1227 }
1228 }
1229 throw new SecurityException("No permission tree found for " + permName);
1230 }
1231
1232 public boolean addPermission(PermissionInfo info) {
1233 synchronized (mPackages) {
1234 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1235 throw new SecurityException("Label must be specified in permission");
1236 }
1237 BasePermission tree = checkPermissionTreeLP(info.name);
1238 BasePermission bp = mSettings.mPermissions.get(info.name);
1239 boolean added = bp == null;
1240 if (added) {
1241 bp = new BasePermission(info.name, tree.sourcePackage,
1242 BasePermission.TYPE_DYNAMIC);
1243 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1244 throw new SecurityException(
1245 "Not allowed to modify non-dynamic permission "
1246 + info.name);
1247 }
1248 bp.perm = new PackageParser.Permission(tree.perm.owner,
1249 new PermissionInfo(info));
1250 bp.perm.info.packageName = tree.perm.info.packageName;
1251 bp.uid = tree.uid;
1252 if (added) {
1253 mSettings.mPermissions.put(info.name, bp);
1254 }
1255 mSettings.writeLP();
1256 return added;
1257 }
1258 }
1259
1260 public void removePermission(String name) {
1261 synchronized (mPackages) {
1262 checkPermissionTreeLP(name);
1263 BasePermission bp = mSettings.mPermissions.get(name);
1264 if (bp != null) {
1265 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1266 throw new SecurityException(
1267 "Not allowed to modify non-dynamic permission "
1268 + name);
1269 }
1270 mSettings.mPermissions.remove(name);
1271 mSettings.writeLP();
1272 }
1273 }
1274 }
1275
Dianne Hackborn854060af2009-07-09 18:14:31 -07001276 public boolean isProtectedBroadcast(String actionName) {
1277 synchronized (mPackages) {
1278 return mProtectedBroadcasts.contains(actionName);
1279 }
1280 }
1281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 public int checkSignatures(String pkg1, String pkg2) {
1283 synchronized (mPackages) {
1284 PackageParser.Package p1 = mPackages.get(pkg1);
1285 PackageParser.Package p2 = mPackages.get(pkg2);
1286 if (p1 == null || p1.mExtras == null
1287 || p2 == null || p2.mExtras == null) {
1288 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1289 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001290 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 }
1292 }
1293
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001294 public int checkUidSignatures(int uid1, int uid2) {
1295 synchronized (mPackages) {
1296 Signature[] s1;
1297 Signature[] s2;
1298 Object obj = mSettings.getUserIdLP(uid1);
1299 if (obj != null) {
1300 if (obj instanceof SharedUserSetting) {
1301 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1302 } else if (obj instanceof PackageSetting) {
1303 s1 = ((PackageSetting)obj).signatures.mSignatures;
1304 } else {
1305 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1306 }
1307 } else {
1308 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1309 }
1310 obj = mSettings.getUserIdLP(uid2);
1311 if (obj != null) {
1312 if (obj instanceof SharedUserSetting) {
1313 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1314 } else if (obj instanceof PackageSetting) {
1315 s2 = ((PackageSetting)obj).signatures.mSignatures;
1316 } else {
1317 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1318 }
1319 } else {
1320 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1321 }
1322 return checkSignaturesLP(s1, s2);
1323 }
1324 }
1325
1326 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1327 if (s1 == null) {
1328 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1330 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1331 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001332 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1334 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001335 final int N1 = s1.length;
1336 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 for (int i=0; i<N1; i++) {
1338 boolean match = false;
1339 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001340 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 match = true;
1342 break;
1343 }
1344 }
1345 if (!match) {
1346 return PackageManager.SIGNATURE_NO_MATCH;
1347 }
1348 }
1349 return PackageManager.SIGNATURE_MATCH;
1350 }
1351
1352 public String[] getPackagesForUid(int uid) {
1353 synchronized (mPackages) {
1354 Object obj = mSettings.getUserIdLP(uid);
1355 if (obj instanceof SharedUserSetting) {
1356 SharedUserSetting sus = (SharedUserSetting)obj;
1357 final int N = sus.packages.size();
1358 String[] res = new String[N];
1359 Iterator<PackageSetting> it = sus.packages.iterator();
1360 int i=0;
1361 while (it.hasNext()) {
1362 res[i++] = it.next().name;
1363 }
1364 return res;
1365 } else if (obj instanceof PackageSetting) {
1366 PackageSetting ps = (PackageSetting)obj;
1367 return new String[] { ps.name };
1368 }
1369 }
1370 return null;
1371 }
1372
1373 public String getNameForUid(int uid) {
1374 synchronized (mPackages) {
1375 Object obj = mSettings.getUserIdLP(uid);
1376 if (obj instanceof SharedUserSetting) {
1377 SharedUserSetting sus = (SharedUserSetting)obj;
1378 return sus.name + ":" + sus.userId;
1379 } else if (obj instanceof PackageSetting) {
1380 PackageSetting ps = (PackageSetting)obj;
1381 return ps.name;
1382 }
1383 }
1384 return null;
1385 }
1386
1387 public int getUidForSharedUser(String sharedUserName) {
1388 if(sharedUserName == null) {
1389 return -1;
1390 }
1391 synchronized (mPackages) {
1392 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1393 if(suid == null) {
1394 return -1;
1395 }
1396 return suid.userId;
1397 }
1398 }
1399
1400 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1401 int flags) {
1402 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001403 return chooseBestActivity(intent, resolvedType, flags, query);
1404 }
1405
Mihai Predaeae850c2009-05-13 10:13:48 +02001406 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1407 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 if (query != null) {
1409 final int N = query.size();
1410 if (N == 1) {
1411 return query.get(0);
1412 } else if (N > 1) {
1413 // If there is more than one activity with the same priority,
1414 // then let the user decide between them.
1415 ResolveInfo r0 = query.get(0);
1416 ResolveInfo r1 = query.get(1);
1417 if (false) {
1418 System.out.println(r0.activityInfo.name +
1419 "=" + r0.priority + " vs " +
1420 r1.activityInfo.name +
1421 "=" + r1.priority);
1422 }
1423 // If the first activity has a higher priority, or a different
1424 // default, then it is always desireable to pick it.
1425 if (r0.priority != r1.priority
1426 || r0.preferredOrder != r1.preferredOrder
1427 || r0.isDefault != r1.isDefault) {
1428 return query.get(0);
1429 }
1430 // If we have saved a preference for a preferred activity for
1431 // this Intent, use that.
1432 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1433 flags, query, r0.priority);
1434 if (ri != null) {
1435 return ri;
1436 }
1437 return mResolveInfo;
1438 }
1439 }
1440 return null;
1441 }
1442
1443 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1444 int flags, List<ResolveInfo> query, int priority) {
1445 synchronized (mPackages) {
1446 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1447 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001448 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1450 if (prefs != null && prefs.size() > 0) {
1451 // First figure out how good the original match set is.
1452 // We will only allow preferred activities that came
1453 // from the same match quality.
1454 int match = 0;
1455 final int N = query.size();
1456 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1457 for (int j=0; j<N; j++) {
1458 ResolveInfo ri = query.get(j);
1459 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1460 + ": 0x" + Integer.toHexString(match));
1461 if (ri.match > match) match = ri.match;
1462 }
1463 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1464 + Integer.toHexString(match));
1465 match &= IntentFilter.MATCH_CATEGORY_MASK;
1466 final int M = prefs.size();
1467 for (int i=0; i<M; i++) {
1468 PreferredActivity pa = prefs.get(i);
1469 if (pa.mMatch != match) {
1470 continue;
1471 }
1472 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1473 if (DEBUG_PREFERRED) {
1474 Log.v(TAG, "Got preferred activity:");
1475 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1476 }
1477 if (ai != null) {
1478 for (int j=0; j<N; j++) {
1479 ResolveInfo ri = query.get(j);
1480 if (!ri.activityInfo.applicationInfo.packageName
1481 .equals(ai.applicationInfo.packageName)) {
1482 continue;
1483 }
1484 if (!ri.activityInfo.name.equals(ai.name)) {
1485 continue;
1486 }
1487
1488 // Okay we found a previously set preferred app.
1489 // If the result set is different from when this
1490 // was created, we need to clear it and re-ask the
1491 // user their preference.
1492 if (!pa.sameSet(query, priority)) {
1493 Log.i(TAG, "Result set changed, dropping preferred activity for "
1494 + intent + " type " + resolvedType);
1495 mSettings.mPreferredActivities.removeFilter(pa);
1496 return null;
1497 }
1498
1499 // Yay!
1500 return ri;
1501 }
1502 }
1503 }
1504 }
1505 }
1506 return null;
1507 }
1508
1509 public List<ResolveInfo> queryIntentActivities(Intent intent,
1510 String resolvedType, int flags) {
1511 ComponentName comp = intent.getComponent();
1512 if (comp != null) {
1513 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1514 ActivityInfo ai = getActivityInfo(comp, flags);
1515 if (ai != null) {
1516 ResolveInfo ri = new ResolveInfo();
1517 ri.activityInfo = ai;
1518 list.add(ri);
1519 }
1520 return list;
1521 }
1522
1523 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001524 String pkgName = intent.getPackage();
1525 if (pkgName == null) {
1526 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1527 resolvedType, flags);
1528 }
1529 PackageParser.Package pkg = mPackages.get(pkgName);
1530 if (pkg != null) {
1531 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1532 resolvedType, flags, pkg.activities);
1533 }
1534 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 }
1536 }
1537
1538 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1539 Intent[] specifics, String[] specificTypes, Intent intent,
1540 String resolvedType, int flags) {
1541 final String resultsAction = intent.getAction();
1542
1543 List<ResolveInfo> results = queryIntentActivities(
1544 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1545 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1546
1547 int specificsPos = 0;
1548 int N;
1549
1550 // todo: note that the algorithm used here is O(N^2). This
1551 // isn't a problem in our current environment, but if we start running
1552 // into situations where we have more than 5 or 10 matches then this
1553 // should probably be changed to something smarter...
1554
1555 // First we go through and resolve each of the specific items
1556 // that were supplied, taking care of removing any corresponding
1557 // duplicate items in the generic resolve list.
1558 if (specifics != null) {
1559 for (int i=0; i<specifics.length; i++) {
1560 final Intent sintent = specifics[i];
1561 if (sintent == null) {
1562 continue;
1563 }
1564
1565 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1566 String action = sintent.getAction();
1567 if (resultsAction != null && resultsAction.equals(action)) {
1568 // If this action was explicitly requested, then don't
1569 // remove things that have it.
1570 action = null;
1571 }
1572 ComponentName comp = sintent.getComponent();
1573 ResolveInfo ri = null;
1574 ActivityInfo ai = null;
1575 if (comp == null) {
1576 ri = resolveIntent(
1577 sintent,
1578 specificTypes != null ? specificTypes[i] : null,
1579 flags);
1580 if (ri == null) {
1581 continue;
1582 }
1583 if (ri == mResolveInfo) {
1584 // ACK! Must do something better with this.
1585 }
1586 ai = ri.activityInfo;
1587 comp = new ComponentName(ai.applicationInfo.packageName,
1588 ai.name);
1589 } else {
1590 ai = getActivityInfo(comp, flags);
1591 if (ai == null) {
1592 continue;
1593 }
1594 }
1595
1596 // Look for any generic query activities that are duplicates
1597 // of this specific one, and remove them from the results.
1598 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1599 N = results.size();
1600 int j;
1601 for (j=specificsPos; j<N; j++) {
1602 ResolveInfo sri = results.get(j);
1603 if ((sri.activityInfo.name.equals(comp.getClassName())
1604 && sri.activityInfo.applicationInfo.packageName.equals(
1605 comp.getPackageName()))
1606 || (action != null && sri.filter.matchAction(action))) {
1607 results.remove(j);
1608 if (Config.LOGV) Log.v(
1609 TAG, "Removing duplicate item from " + j
1610 + " due to specific " + specificsPos);
1611 if (ri == null) {
1612 ri = sri;
1613 }
1614 j--;
1615 N--;
1616 }
1617 }
1618
1619 // Add this specific item to its proper place.
1620 if (ri == null) {
1621 ri = new ResolveInfo();
1622 ri.activityInfo = ai;
1623 }
1624 results.add(specificsPos, ri);
1625 ri.specificIndex = i;
1626 specificsPos++;
1627 }
1628 }
1629
1630 // Now we go through the remaining generic results and remove any
1631 // duplicate actions that are found here.
1632 N = results.size();
1633 for (int i=specificsPos; i<N-1; i++) {
1634 final ResolveInfo rii = results.get(i);
1635 if (rii.filter == null) {
1636 continue;
1637 }
1638
1639 // Iterate over all of the actions of this result's intent
1640 // filter... typically this should be just one.
1641 final Iterator<String> it = rii.filter.actionsIterator();
1642 if (it == null) {
1643 continue;
1644 }
1645 while (it.hasNext()) {
1646 final String action = it.next();
1647 if (resultsAction != null && resultsAction.equals(action)) {
1648 // If this action was explicitly requested, then don't
1649 // remove things that have it.
1650 continue;
1651 }
1652 for (int j=i+1; j<N; j++) {
1653 final ResolveInfo rij = results.get(j);
1654 if (rij.filter != null && rij.filter.hasAction(action)) {
1655 results.remove(j);
1656 if (Config.LOGV) Log.v(
1657 TAG, "Removing duplicate item from " + j
1658 + " due to action " + action + " at " + i);
1659 j--;
1660 N--;
1661 }
1662 }
1663 }
1664
1665 // If the caller didn't request filter information, drop it now
1666 // so we don't have to marshall/unmarshall it.
1667 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1668 rii.filter = null;
1669 }
1670 }
1671
1672 // Filter out the caller activity if so requested.
1673 if (caller != null) {
1674 N = results.size();
1675 for (int i=0; i<N; i++) {
1676 ActivityInfo ainfo = results.get(i).activityInfo;
1677 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1678 && caller.getClassName().equals(ainfo.name)) {
1679 results.remove(i);
1680 break;
1681 }
1682 }
1683 }
1684
1685 // If the caller didn't request filter information,
1686 // drop them now so we don't have to
1687 // marshall/unmarshall it.
1688 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1689 N = results.size();
1690 for (int i=0; i<N; i++) {
1691 results.get(i).filter = null;
1692 }
1693 }
1694
1695 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1696 return results;
1697 }
1698
1699 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1700 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001701 ComponentName comp = intent.getComponent();
1702 if (comp != null) {
1703 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1704 ActivityInfo ai = getReceiverInfo(comp, flags);
1705 if (ai != null) {
1706 ResolveInfo ri = new ResolveInfo();
1707 ri.activityInfo = ai;
1708 list.add(ri);
1709 }
1710 return list;
1711 }
1712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001714 String pkgName = intent.getPackage();
1715 if (pkgName == null) {
1716 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1717 resolvedType, flags);
1718 }
1719 PackageParser.Package pkg = mPackages.get(pkgName);
1720 if (pkg != null) {
1721 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1722 resolvedType, flags, pkg.receivers);
1723 }
1724 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 }
1726 }
1727
1728 public ResolveInfo resolveService(Intent intent, String resolvedType,
1729 int flags) {
1730 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1731 flags);
1732 if (query != null) {
1733 if (query.size() >= 1) {
1734 // If there is more than one service with the same priority,
1735 // just arbitrarily pick the first one.
1736 return query.get(0);
1737 }
1738 }
1739 return null;
1740 }
1741
1742 public List<ResolveInfo> queryIntentServices(Intent intent,
1743 String resolvedType, int flags) {
1744 ComponentName comp = intent.getComponent();
1745 if (comp != null) {
1746 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1747 ServiceInfo si = getServiceInfo(comp, flags);
1748 if (si != null) {
1749 ResolveInfo ri = new ResolveInfo();
1750 ri.serviceInfo = si;
1751 list.add(ri);
1752 }
1753 return list;
1754 }
1755
1756 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001757 String pkgName = intent.getPackage();
1758 if (pkgName == null) {
1759 return (List<ResolveInfo>)mServices.queryIntent(intent,
1760 resolvedType, flags);
1761 }
1762 PackageParser.Package pkg = mPackages.get(pkgName);
1763 if (pkg != null) {
1764 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1765 resolvedType, flags, pkg.services);
1766 }
1767 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 }
1769 }
1770
1771 public List<PackageInfo> getInstalledPackages(int flags) {
1772 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1773
1774 synchronized (mPackages) {
1775 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1776 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1777 while (i.hasNext()) {
1778 final PackageSetting ps = i.next();
1779 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1780 if(psPkg != null) {
1781 finalList.add(psPkg);
1782 }
1783 }
1784 }
1785 else {
1786 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1787 while (i.hasNext()) {
1788 final PackageParser.Package p = i.next();
1789 if (p.applicationInfo != null) {
1790 PackageInfo pi = generatePackageInfo(p, flags);
1791 if(pi != null) {
1792 finalList.add(pi);
1793 }
1794 }
1795 }
1796 }
1797 }
1798 return finalList;
1799 }
1800
1801 public List<ApplicationInfo> getInstalledApplications(int flags) {
1802 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1803 synchronized(mPackages) {
1804 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1805 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1806 while (i.hasNext()) {
1807 final PackageSetting ps = i.next();
1808 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1809 if(ai != null) {
1810 finalList.add(ai);
1811 }
1812 }
1813 }
1814 else {
1815 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1816 while (i.hasNext()) {
1817 final PackageParser.Package p = i.next();
1818 if (p.applicationInfo != null) {
1819 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1820 if(ai != null) {
1821 finalList.add(ai);
1822 }
1823 }
1824 }
1825 }
1826 }
1827 return finalList;
1828 }
1829
1830 public List<ApplicationInfo> getPersistentApplications(int flags) {
1831 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1832
1833 synchronized (mPackages) {
1834 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1835 while (i.hasNext()) {
1836 PackageParser.Package p = i.next();
1837 if (p.applicationInfo != null
1838 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1839 && (!mSafeMode || (p.applicationInfo.flags
1840 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1841 finalList.add(p.applicationInfo);
1842 }
1843 }
1844 }
1845
1846 return finalList;
1847 }
1848
1849 public ProviderInfo resolveContentProvider(String name, int flags) {
1850 synchronized (mPackages) {
1851 final PackageParser.Provider provider = mProviders.get(name);
1852 return provider != null
1853 && mSettings.isEnabledLP(provider.info, flags)
1854 && (!mSafeMode || (provider.info.applicationInfo.flags
1855 &ApplicationInfo.FLAG_SYSTEM) != 0)
1856 ? PackageParser.generateProviderInfo(provider, flags)
1857 : null;
1858 }
1859 }
1860
Fred Quintana718d8a22009-04-29 17:53:20 -07001861 /**
1862 * @deprecated
1863 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 public void querySyncProviders(List outNames, List outInfo) {
1865 synchronized (mPackages) {
1866 Iterator<Map.Entry<String, PackageParser.Provider>> i
1867 = mProviders.entrySet().iterator();
1868
1869 while (i.hasNext()) {
1870 Map.Entry<String, PackageParser.Provider> entry = i.next();
1871 PackageParser.Provider p = entry.getValue();
1872
1873 if (p.syncable
1874 && (!mSafeMode || (p.info.applicationInfo.flags
1875 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1876 outNames.add(entry.getKey());
1877 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1878 }
1879 }
1880 }
1881 }
1882
1883 public List<ProviderInfo> queryContentProviders(String processName,
1884 int uid, int flags) {
1885 ArrayList<ProviderInfo> finalList = null;
1886
1887 synchronized (mPackages) {
1888 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1889 while (i.hasNext()) {
1890 PackageParser.Provider p = i.next();
1891 if (p.info.authority != null
1892 && (processName == null ||
1893 (p.info.processName.equals(processName)
1894 && p.info.applicationInfo.uid == uid))
1895 && mSettings.isEnabledLP(p.info, flags)
1896 && (!mSafeMode || (p.info.applicationInfo.flags
1897 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1898 if (finalList == null) {
1899 finalList = new ArrayList<ProviderInfo>(3);
1900 }
1901 finalList.add(PackageParser.generateProviderInfo(p,
1902 flags));
1903 }
1904 }
1905 }
1906
1907 if (finalList != null) {
1908 Collections.sort(finalList, mProviderInitOrderSorter);
1909 }
1910
1911 return finalList;
1912 }
1913
1914 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1915 int flags) {
1916 synchronized (mPackages) {
1917 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1918 return PackageParser.generateInstrumentationInfo(i, flags);
1919 }
1920 }
1921
1922 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1923 int flags) {
1924 ArrayList<InstrumentationInfo> finalList =
1925 new ArrayList<InstrumentationInfo>();
1926
1927 synchronized (mPackages) {
1928 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1929 while (i.hasNext()) {
1930 PackageParser.Instrumentation p = i.next();
1931 if (targetPackage == null
1932 || targetPackage.equals(p.info.targetPackage)) {
1933 finalList.add(PackageParser.generateInstrumentationInfo(p,
1934 flags));
1935 }
1936 }
1937 }
1938
1939 return finalList;
1940 }
1941
1942 private void scanDirLI(File dir, int flags, int scanMode) {
1943 Log.d(TAG, "Scanning app dir " + dir);
1944
1945 String[] files = dir.list();
1946
1947 int i;
1948 for (i=0; i<files.length; i++) {
1949 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001950 File resFile = file;
1951 // Pick up the resource path from settings for fwd locked apps
1952 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1953 resFile = null;
1954 }
1955 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1957 }
1958 }
1959
1960 private static void reportSettingsProblem(int priority, String msg) {
1961 try {
1962 File dataDir = Environment.getDataDirectory();
1963 File systemDir = new File(dataDir, "system");
1964 File fname = new File(systemDir, "uiderrors.txt");
1965 FileOutputStream out = new FileOutputStream(fname, true);
1966 PrintWriter pw = new PrintWriter(out);
1967 pw.println(msg);
1968 pw.close();
1969 FileUtils.setPermissions(
1970 fname.toString(),
1971 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1972 -1, -1);
1973 } catch (java.io.IOException e) {
1974 }
1975 Log.println(priority, TAG, msg);
1976 }
1977
1978 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1979 PackageParser.Package pkg, File srcFile, int parseFlags) {
1980 if (GET_CERTIFICATES) {
1981 if (ps == null || !ps.codePath.equals(srcFile)
1982 || ps.getTimeStamp() != srcFile.lastModified()) {
1983 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1984 if (!pp.collectCertificates(pkg, parseFlags)) {
1985 mLastScanError = pp.getParseError();
1986 return false;
1987 }
1988 }
1989 }
1990 return true;
1991 }
1992
1993 /*
1994 * Scan a package and return the newly parsed package.
1995 * Returns null in case of errors and the error code is stored in mLastScanError
1996 */
1997 private PackageParser.Package scanPackageLI(File scanFile,
1998 File destCodeFile, File destResourceFile, int parseFlags,
1999 int scanMode) {
2000 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2001 parseFlags |= mDefParseFlags;
2002 PackageParser pp = new PackageParser(scanFile.getPath());
2003 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 final PackageParser.Package pkg = pp.parsePackage(scanFile,
2005 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
2006 if (pkg == null) {
2007 mLastScanError = pp.getParseError();
2008 return null;
2009 }
2010 PackageSetting ps;
2011 PackageSetting updatedPkg;
2012 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002013 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2015 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002016 // Verify certificates first
2017 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2018 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2019 return null;
2020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 if (updatedPkg != null) {
2022 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2023 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2024 }
2025 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2026 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002027 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2028 if (pkg.mVersionCode < ps.versionCode) {
2029 // The system package has been updated and the code path does not match
2030 // Ignore entry. Just return
2031 Log.w(TAG, "Package:" + pkg.packageName +
2032 " has been updated. Ignoring the one from path:"+scanFile);
2033 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2034 return null;
2035 } else {
2036 // Delete the older apk pointed to by ps
2037 // At this point, its safely assumed that package installation for
2038 // apps in system partition will go through. If not there won't be a working
2039 // version of the app
2040 synchronized (mPackages) {
2041 // Just remove the loaded entries from package lists.
2042 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002043 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002044 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2045 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 }
2048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 // The apk is forward locked (not public) if its code and resources
2050 // are kept in different files.
2051 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2052 scanMode |= SCAN_FORWARD_LOCKED;
2053 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002054 File resFile = destResourceFile;
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002055 if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002056 resFile = getFwdLockedResource(ps.name);
2057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002059 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2061 }
2062
2063 private static String fixProcessName(String defProcessName,
2064 String processName, int uid) {
2065 if (processName == null) {
2066 return defProcessName;
2067 }
2068 return processName;
2069 }
2070
2071 private boolean verifySignaturesLP(PackageSetting pkgSetting,
2072 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2073 if (pkg.mSignatures != null) {
2074 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2075 updateSignature)) {
2076 Log.e(TAG, "Package " + pkg.packageName
2077 + " signatures do not match the previously installed version; ignoring!");
2078 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2079 return false;
2080 }
2081
2082 if (pkgSetting.sharedUser != null) {
2083 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2084 pkg.mSignatures, updateSignature)) {
2085 Log.e(TAG, "Package " + pkg.packageName
2086 + " has no signatures that match those in shared user "
2087 + pkgSetting.sharedUser.name + "; ignoring!");
2088 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2089 return false;
2090 }
2091 }
2092 } else {
2093 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2094 }
2095 return true;
2096 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002097
2098 public boolean performDexOpt(String packageName) {
2099 if (!mNoDexOpt) {
2100 return false;
2101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002103 PackageParser.Package p;
2104 synchronized (mPackages) {
2105 p = mPackages.get(packageName);
2106 if (p == null || p.mDidDexOpt) {
2107 return false;
2108 }
2109 }
2110 synchronized (mInstallLock) {
2111 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2112 }
2113 }
2114
2115 static final int DEX_OPT_SKIPPED = 0;
2116 static final int DEX_OPT_PERFORMED = 1;
2117 static final int DEX_OPT_FAILED = -1;
2118
2119 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2120 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002121 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002122 String path = pkg.mScanPath;
2123 int ret = 0;
2124 try {
2125 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2126 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2127 !pkg.mForwardLocked);
2128 pkg.mDidDexOpt = true;
2129 performed = true;
2130 }
2131 } catch (FileNotFoundException e) {
2132 Log.w(TAG, "Apk not found for dexopt: " + path);
2133 ret = -1;
2134 } catch (IOException e) {
2135 Log.w(TAG, "Exception reading apk: " + path, e);
2136 ret = -1;
2137 }
2138 if (ret < 0) {
2139 //error from installer
2140 return DEX_OPT_FAILED;
2141 }
2142 }
2143
2144 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2145 }
2146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 private PackageParser.Package scanPackageLI(
2148 File scanFile, File destCodeFile, File destResourceFile,
2149 PackageParser.Package pkg, int parseFlags, int scanMode) {
2150
2151 mScanningPath = scanFile;
2152 if (pkg == null) {
2153 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2154 return null;
2155 }
2156
2157 final String pkgName = pkg.applicationInfo.packageName;
2158 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2159 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2160 }
2161
2162 if (pkgName.equals("android")) {
2163 synchronized (mPackages) {
2164 if (mAndroidApplication != null) {
2165 Log.w(TAG, "*************************************************");
2166 Log.w(TAG, "Core android package being redefined. Skipping.");
2167 Log.w(TAG, " file=" + mScanningPath);
2168 Log.w(TAG, "*************************************************");
2169 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2170 return null;
2171 }
2172
2173 // Set up information for our fall-back user intent resolution
2174 // activity.
2175 mPlatformPackage = pkg;
2176 pkg.mVersionCode = mSdkVersion;
2177 mAndroidApplication = pkg.applicationInfo;
2178 mResolveActivity.applicationInfo = mAndroidApplication;
2179 mResolveActivity.name = ResolverActivity.class.getName();
2180 mResolveActivity.packageName = mAndroidApplication.packageName;
2181 mResolveActivity.processName = mAndroidApplication.processName;
2182 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2183 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2184 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2185 mResolveActivity.exported = true;
2186 mResolveActivity.enabled = true;
2187 mResolveInfo.activityInfo = mResolveActivity;
2188 mResolveInfo.priority = 0;
2189 mResolveInfo.preferredOrder = 0;
2190 mResolveInfo.match = 0;
2191 mResolveComponentName = new ComponentName(
2192 mAndroidApplication.packageName, mResolveActivity.name);
2193 }
2194 }
2195
2196 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2197 TAG, "Scanning package " + pkgName);
2198 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2199 Log.w(TAG, "*************************************************");
2200 Log.w(TAG, "Application package " + pkgName
2201 + " already installed. Skipping duplicate.");
2202 Log.w(TAG, "*************************************************");
2203 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2204 return null;
2205 }
2206
2207 SharedUserSetting suid = null;
2208 PackageSetting pkgSetting = null;
2209
2210 boolean removeExisting = false;
2211
2212 synchronized (mPackages) {
2213 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002214 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2215 if (mTmpSharedLibraries == null ||
2216 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2217 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2218 }
2219 int num = 0;
2220 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2221 for (int i=0; i<N; i++) {
2222 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 if (file == null) {
2224 Log.e(TAG, "Package " + pkg.packageName
2225 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002226 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2228 return null;
2229 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002230 mTmpSharedLibraries[num] = file;
2231 num++;
2232 }
2233 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2234 for (int i=0; i<N; i++) {
2235 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2236 if (file == null) {
2237 Log.w(TAG, "Package " + pkg.packageName
2238 + " desires unavailable shared library "
2239 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2240 } else {
2241 mTmpSharedLibraries[num] = file;
2242 num++;
2243 }
2244 }
2245 if (num > 0) {
2246 pkg.usesLibraryFiles = new String[num];
2247 System.arraycopy(mTmpSharedLibraries, 0,
2248 pkg.usesLibraryFiles, 0, num);
2249 }
2250
2251 if (pkg.reqFeatures != null) {
2252 N = pkg.reqFeatures.size();
2253 for (int i=0; i<N; i++) {
2254 FeatureInfo fi = pkg.reqFeatures.get(i);
2255 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2256 // Don't care.
2257 continue;
2258 }
2259
2260 if (fi.name != null) {
2261 if (mAvailableFeatures.get(fi.name) == null) {
2262 Log.e(TAG, "Package " + pkg.packageName
2263 + " requires unavailable feature "
2264 + fi.name + "; failing!");
2265 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2266 return null;
2267 }
2268 }
2269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 }
2271 }
2272
2273 if (pkg.mSharedUserId != null) {
2274 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2275 pkg.applicationInfo.flags, true);
2276 if (suid == null) {
2277 Log.w(TAG, "Creating application package " + pkgName
2278 + " for shared user failed");
2279 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2280 return null;
2281 }
2282 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2283 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2284 + suid.userId + "): packages=" + suid.packages);
2285 }
2286 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002287
2288 // Just create the setting, don't add it yet. For already existing packages
2289 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2291 destResourceFile, pkg.applicationInfo.flags, true, false);
2292 if (pkgSetting == null) {
2293 Log.w(TAG, "Creating application package " + pkgName + " failed");
2294 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2295 return null;
2296 }
2297 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2298 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2299 }
2300
2301 pkg.applicationInfo.uid = pkgSetting.userId;
2302 pkg.mExtras = pkgSetting;
2303
2304 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
2305 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2306 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2307 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2308 return null;
2309 }
2310 // The signature has changed, but this package is in the system
2311 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002312 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 // However... if this package is part of a shared user, but it
2314 // doesn't match the signature of the shared user, let's fail.
2315 // What this means is that you can't change the signatures
2316 // associated with an overall shared user, which doesn't seem all
2317 // that unreasonable.
2318 if (pkgSetting.sharedUser != null) {
2319 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2320 pkg.mSignatures, false)) {
2321 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2322 return null;
2323 }
2324 }
2325 removeExisting = true;
2326 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002327
2328 // Verify that this new package doesn't have any content providers
2329 // that conflict with existing packages. Only do this if the
2330 // package isn't already installed, since we don't want to break
2331 // things that are installed.
2332 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2333 int N = pkg.providers.size();
2334 int i;
2335 for (i=0; i<N; i++) {
2336 PackageParser.Provider p = pkg.providers.get(i);
2337 String names[] = p.info.authority.split(";");
2338 for (int j = 0; j < names.length; j++) {
2339 if (mProviders.containsKey(names[j])) {
2340 PackageParser.Provider other = mProviders.get(names[j]);
2341 Log.w(TAG, "Can't install because provider name " + names[j] +
2342 " (in package " + pkg.applicationInfo.packageName +
2343 ") is already used by "
2344 + ((other != null && other.component != null)
2345 ? other.component.getPackageName() : "?"));
2346 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2347 return null;
2348 }
2349 }
2350 }
2351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 }
2353
2354 if (removeExisting) {
2355 if (mInstaller != null) {
2356 int ret = mInstaller.remove(pkgName);
2357 if (ret != 0) {
2358 String msg = "System package " + pkg.packageName
2359 + " could not have data directory erased after signature change.";
2360 reportSettingsProblem(Log.WARN, msg);
2361 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2362 return null;
2363 }
2364 }
2365 Log.w(TAG, "System package " + pkg.packageName
2366 + " signature changed: existing data removed.");
2367 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2368 }
2369
2370 long scanFileTime = scanFile.lastModified();
2371 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2372 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2373 pkg.applicationInfo.processName = fixProcessName(
2374 pkg.applicationInfo.packageName,
2375 pkg.applicationInfo.processName,
2376 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002377 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378
2379 File dataPath;
2380 if (mPlatformPackage == pkg) {
2381 // The system package is special.
2382 dataPath = new File (Environment.getDataDirectory(), "system");
2383 pkg.applicationInfo.dataDir = dataPath.getPath();
2384 } else {
2385 // This is a normal package, need to make its data directory.
2386 dataPath = new File(mAppDataDir, pkgName);
2387 if (dataPath.exists()) {
2388 mOutPermissions[1] = 0;
2389 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2390 if (mOutPermissions[1] == pkg.applicationInfo.uid
2391 || !Process.supportsProcesses()) {
2392 pkg.applicationInfo.dataDir = dataPath.getPath();
2393 } else {
2394 boolean recovered = false;
2395 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2396 // If this is a system app, we can at least delete its
2397 // current data so the application will still work.
2398 if (mInstaller != null) {
2399 int ret = mInstaller.remove(pkgName);
2400 if(ret >= 0) {
2401 // Old data gone!
2402 String msg = "System package " + pkg.packageName
2403 + " has changed from uid: "
2404 + mOutPermissions[1] + " to "
2405 + pkg.applicationInfo.uid + "; old data erased";
2406 reportSettingsProblem(Log.WARN, msg);
2407 recovered = true;
2408
2409 // And now re-install the app.
2410 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2411 pkg.applicationInfo.uid);
2412 if (ret == -1) {
2413 // Ack should not happen!
2414 msg = "System package " + pkg.packageName
2415 + " could not have data directory re-created after delete.";
2416 reportSettingsProblem(Log.WARN, msg);
2417 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2418 return null;
2419 }
2420 }
2421 }
2422 if (!recovered) {
2423 mHasSystemUidErrors = true;
2424 }
2425 }
2426 if (!recovered) {
2427 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2428 + pkg.applicationInfo.uid + "/fs_"
2429 + mOutPermissions[1];
2430 String msg = "Package " + pkg.packageName
2431 + " has mismatched uid: "
2432 + mOutPermissions[1] + " on disk, "
2433 + pkg.applicationInfo.uid + " in settings";
2434 synchronized (mPackages) {
2435 if (!mReportedUidError) {
2436 mReportedUidError = true;
2437 msg = msg + "; read messages:\n"
2438 + mSettings.getReadMessagesLP();
2439 }
2440 reportSettingsProblem(Log.ERROR, msg);
2441 }
2442 }
2443 }
2444 pkg.applicationInfo.dataDir = dataPath.getPath();
2445 } else {
2446 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2447 Log.v(TAG, "Want this data dir: " + dataPath);
2448 //invoke installer to do the actual installation
2449 if (mInstaller != null) {
2450 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2451 pkg.applicationInfo.uid);
2452 if(ret < 0) {
2453 // Error from installer
2454 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2455 return null;
2456 }
2457 } else {
2458 dataPath.mkdirs();
2459 if (dataPath.exists()) {
2460 FileUtils.setPermissions(
2461 dataPath.toString(),
2462 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2463 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2464 }
2465 }
2466 if (dataPath.exists()) {
2467 pkg.applicationInfo.dataDir = dataPath.getPath();
2468 } else {
2469 Log.w(TAG, "Unable to create data directory: " + dataPath);
2470 pkg.applicationInfo.dataDir = null;
2471 }
2472 }
2473 }
2474
2475 // Perform shared library installation and dex validation and
2476 // optimization, if this is not a system app.
2477 if (mInstaller != null) {
2478 String path = scanFile.getPath();
2479 if (scanFileNewer) {
2480 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002481 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2482 if (err != PackageManager.INSTALL_SUCCEEDED) {
2483 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 return null;
2485 }
2486 }
2487
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002488 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2489 pkg.mScanPath = path;
2490
2491 if ((scanMode&SCAN_NO_DEX) == 0) {
2492 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2494 return null;
2495 }
2496 }
2497 }
2498
2499 if (mFactoryTest && pkg.requestedPermissions.contains(
2500 android.Manifest.permission.FACTORY_TEST)) {
2501 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2502 }
2503
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002504 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 if ((scanMode&SCAN_MONITOR) != 0) {
2506 pkg.mPath = destCodeFile.getAbsolutePath();
2507 mAppDirs.put(pkg.mPath, pkg);
2508 }
2509
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002510 // Request the ActivityManager to kill the process(only for existing packages)
2511 // so that we do not end up in a confused state while the user is still using the older
2512 // version of the application while the new one gets installed.
2513 IActivityManager am = ActivityManagerNative.getDefault();
2514 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2515 try {
2516 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2517 pkg.applicationInfo.uid);
2518 } catch (RemoteException e) {
2519 }
2520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002523 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002525 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 int N = pkg.providers.size();
2527 StringBuilder r = null;
2528 int i;
2529 for (i=0; i<N; i++) {
2530 PackageParser.Provider p = pkg.providers.get(i);
2531 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2532 p.info.processName, pkg.applicationInfo.uid);
2533 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2534 p.info.name), p);
2535 p.syncable = p.info.isSyncable;
2536 String names[] = p.info.authority.split(";");
2537 p.info.authority = null;
2538 for (int j = 0; j < names.length; j++) {
2539 if (j == 1 && p.syncable) {
2540 // We only want the first authority for a provider to possibly be
2541 // syncable, so if we already added this provider using a different
2542 // authority clear the syncable flag. We copy the provider before
2543 // changing it because the mProviders object contains a reference
2544 // to a provider that we don't want to change.
2545 // Only do this for the second authority since the resulting provider
2546 // object can be the same for all future authorities for this provider.
2547 p = new PackageParser.Provider(p);
2548 p.syncable = false;
2549 }
2550 if (!mProviders.containsKey(names[j])) {
2551 mProviders.put(names[j], p);
2552 if (p.info.authority == null) {
2553 p.info.authority = names[j];
2554 } else {
2555 p.info.authority = p.info.authority + ";" + names[j];
2556 }
2557 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2558 Log.d(TAG, "Registered content provider: " + names[j] +
2559 ", className = " + p.info.name +
2560 ", isSyncable = " + p.info.isSyncable);
2561 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002562 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 Log.w(TAG, "Skipping provider name " + names[j] +
2564 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002565 "): name already used by "
2566 + ((other != null && other.component != null)
2567 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 }
2569 }
2570 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2571 if (r == null) {
2572 r = new StringBuilder(256);
2573 } else {
2574 r.append(' ');
2575 }
2576 r.append(p.info.name);
2577 }
2578 }
2579 if (r != null) {
2580 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2581 }
2582
2583 N = pkg.services.size();
2584 r = null;
2585 for (i=0; i<N; i++) {
2586 PackageParser.Service s = pkg.services.get(i);
2587 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2588 s.info.processName, pkg.applicationInfo.uid);
2589 mServices.addService(s);
2590 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2591 if (r == null) {
2592 r = new StringBuilder(256);
2593 } else {
2594 r.append(' ');
2595 }
2596 r.append(s.info.name);
2597 }
2598 }
2599 if (r != null) {
2600 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2601 }
2602
2603 N = pkg.receivers.size();
2604 r = null;
2605 for (i=0; i<N; i++) {
2606 PackageParser.Activity a = pkg.receivers.get(i);
2607 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2608 a.info.processName, pkg.applicationInfo.uid);
2609 mReceivers.addActivity(a, "receiver");
2610 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2611 if (r == null) {
2612 r = new StringBuilder(256);
2613 } else {
2614 r.append(' ');
2615 }
2616 r.append(a.info.name);
2617 }
2618 }
2619 if (r != null) {
2620 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2621 }
2622
2623 N = pkg.activities.size();
2624 r = null;
2625 for (i=0; i<N; i++) {
2626 PackageParser.Activity a = pkg.activities.get(i);
2627 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2628 a.info.processName, pkg.applicationInfo.uid);
2629 mActivities.addActivity(a, "activity");
2630 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2631 if (r == null) {
2632 r = new StringBuilder(256);
2633 } else {
2634 r.append(' ');
2635 }
2636 r.append(a.info.name);
2637 }
2638 }
2639 if (r != null) {
2640 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2641 }
2642
2643 N = pkg.permissionGroups.size();
2644 r = null;
2645 for (i=0; i<N; i++) {
2646 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2647 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2648 if (cur == null) {
2649 mPermissionGroups.put(pg.info.name, pg);
2650 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2651 if (r == null) {
2652 r = new StringBuilder(256);
2653 } else {
2654 r.append(' ');
2655 }
2656 r.append(pg.info.name);
2657 }
2658 } else {
2659 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2660 + pg.info.packageName + " ignored: original from "
2661 + cur.info.packageName);
2662 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2663 if (r == null) {
2664 r = new StringBuilder(256);
2665 } else {
2666 r.append(' ');
2667 }
2668 r.append("DUP:");
2669 r.append(pg.info.name);
2670 }
2671 }
2672 }
2673 if (r != null) {
2674 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2675 }
2676
2677 N = pkg.permissions.size();
2678 r = null;
2679 for (i=0; i<N; i++) {
2680 PackageParser.Permission p = pkg.permissions.get(i);
2681 HashMap<String, BasePermission> permissionMap =
2682 p.tree ? mSettings.mPermissionTrees
2683 : mSettings.mPermissions;
2684 p.group = mPermissionGroups.get(p.info.group);
2685 if (p.info.group == null || p.group != null) {
2686 BasePermission bp = permissionMap.get(p.info.name);
2687 if (bp == null) {
2688 bp = new BasePermission(p.info.name, p.info.packageName,
2689 BasePermission.TYPE_NORMAL);
2690 permissionMap.put(p.info.name, bp);
2691 }
2692 if (bp.perm == null) {
2693 if (bp.sourcePackage == null
2694 || bp.sourcePackage.equals(p.info.packageName)) {
2695 BasePermission tree = findPermissionTreeLP(p.info.name);
2696 if (tree == null
2697 || tree.sourcePackage.equals(p.info.packageName)) {
2698 bp.perm = p;
2699 bp.uid = pkg.applicationInfo.uid;
2700 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2701 if (r == null) {
2702 r = new StringBuilder(256);
2703 } else {
2704 r.append(' ');
2705 }
2706 r.append(p.info.name);
2707 }
2708 } else {
2709 Log.w(TAG, "Permission " + p.info.name + " from package "
2710 + p.info.packageName + " ignored: base tree "
2711 + tree.name + " is from package "
2712 + tree.sourcePackage);
2713 }
2714 } else {
2715 Log.w(TAG, "Permission " + p.info.name + " from package "
2716 + p.info.packageName + " ignored: original from "
2717 + bp.sourcePackage);
2718 }
2719 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2720 if (r == null) {
2721 r = new StringBuilder(256);
2722 } else {
2723 r.append(' ');
2724 }
2725 r.append("DUP:");
2726 r.append(p.info.name);
2727 }
2728 } else {
2729 Log.w(TAG, "Permission " + p.info.name + " from package "
2730 + p.info.packageName + " ignored: no group "
2731 + p.group);
2732 }
2733 }
2734 if (r != null) {
2735 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2736 }
2737
2738 N = pkg.instrumentation.size();
2739 r = null;
2740 for (i=0; i<N; i++) {
2741 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2742 a.info.packageName = pkg.applicationInfo.packageName;
2743 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2744 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2745 a.info.dataDir = pkg.applicationInfo.dataDir;
2746 mInstrumentation.put(a.component, a);
2747 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2748 if (r == null) {
2749 r = new StringBuilder(256);
2750 } else {
2751 r.append(' ');
2752 }
2753 r.append(a.info.name);
2754 }
2755 }
2756 if (r != null) {
2757 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2758 }
2759
Dianne Hackborn854060af2009-07-09 18:14:31 -07002760 if (pkg.protectedBroadcasts != null) {
2761 N = pkg.protectedBroadcasts.size();
2762 for (i=0; i<N; i++) {
2763 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2764 }
2765 }
2766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 pkgSetting.setTimeStamp(scanFileTime);
2768 }
2769
2770 return pkg;
2771 }
2772
Dianne Hackbornb1811182009-05-21 15:45:42 -07002773 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2774 File dataPath, File scanFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002776 final String sharedLibraryABI = Build.CPU_ABI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002777 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2778 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2779 final String sharedLibrarySuffix = ".so";
Dianne Hackbornb1811182009-05-21 15:45:42 -07002780 boolean hasNativeCode = false;
2781 boolean installedNativeCode = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002782 try {
2783 ZipFile zipFile = new ZipFile(scanFile);
2784 Enumeration<ZipEntry> entries =
2785 (Enumeration<ZipEntry>) zipFile.entries();
2786
2787 while (entries.hasMoreElements()) {
2788 ZipEntry entry = entries.nextElement();
2789 if (entry.isDirectory()) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002790 if (!hasNativeCode && entry.getName().startsWith("lib")) {
2791 hasNativeCode = true;
2792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 continue;
2794 }
2795 String entryName = entry.getName();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002796 if (entryName.startsWith("lib/")) {
2797 hasNativeCode = true;
2798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2800 && entryName.endsWith(sharedLibrarySuffix))) {
2801 continue;
2802 }
2803 String libFileName = entryName.substring(
2804 apkLibraryDirectory.length());
2805 if (libFileName.contains("/")
2806 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2807 continue;
2808 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002809
2810 installedNativeCode = true;
2811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2813 File.separator + libFileName;
2814 File sharedLibraryFile = new File(sharedLibraryFilePath);
2815 if (! sharedLibraryFile.exists() ||
2816 sharedLibraryFile.length() != entry.getSize() ||
2817 sharedLibraryFile.lastModified() != entry.getTime()) {
2818 if (Config.LOGD) {
2819 Log.d(TAG, "Caching shared lib " + entry.getName());
2820 }
2821 if (mInstaller == null) {
2822 sharedLibraryDir.mkdir();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 }
2824 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2825 sharedLibraryFile);
2826 }
2827 }
2828 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002829 Log.w(TAG, "Failed to cache package shared libs", e);
2830 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002832
2833 if (hasNativeCode && !installedNativeCode) {
2834 Log.w(TAG, "Install failed: .apk has native code but none for arch "
2835 + Build.CPU_ABI);
2836 return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
2837 }
2838
2839 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 }
2841
2842 private void cacheSharedLibLI(PackageParser.Package pkg,
2843 ZipFile zipFile, ZipEntry entry,
2844 File sharedLibraryDir,
2845 File sharedLibraryFile) throws IOException {
2846 InputStream inputStream = zipFile.getInputStream(entry);
2847 try {
2848 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2849 String tempFilePath = tempFile.getPath();
2850 // XXX package manager can't change owner, so the lib files for
2851 // now need to be left as world readable and owned by the system.
2852 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2853 ! tempFile.setLastModified(entry.getTime()) ||
2854 FileUtils.setPermissions(tempFilePath,
2855 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2856 |FileUtils.S_IROTH, -1, -1) != 0 ||
2857 ! tempFile.renameTo(sharedLibraryFile)) {
2858 // Failed to properly write file.
2859 tempFile.delete();
2860 throw new IOException("Couldn't create cached shared lib "
2861 + sharedLibraryFile + " in " + sharedLibraryDir);
2862 }
2863 } finally {
2864 inputStream.close();
2865 }
2866 }
2867
2868 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2869 if (chatty && Config.LOGD) Log.d(
2870 TAG, "Removing package " + pkg.applicationInfo.packageName );
2871
2872 synchronized (mPackages) {
2873 if (pkg.mPreferredOrder > 0) {
2874 mSettings.mPreferredPackages.remove(pkg);
2875 pkg.mPreferredOrder = 0;
2876 updatePreferredIndicesLP();
2877 }
2878
2879 clearPackagePreferredActivitiesLP(pkg.packageName);
2880
2881 mPackages.remove(pkg.applicationInfo.packageName);
2882 if (pkg.mPath != null) {
2883 mAppDirs.remove(pkg.mPath);
2884 }
2885
2886 PackageSetting ps = (PackageSetting)pkg.mExtras;
2887 if (ps != null && ps.sharedUser != null) {
2888 // XXX don't do this until the data is removed.
2889 if (false) {
2890 ps.sharedUser.packages.remove(ps);
2891 if (ps.sharedUser.packages.size() == 0) {
2892 // Remove.
2893 }
2894 }
2895 }
2896
2897 int N = pkg.providers.size();
2898 StringBuilder r = null;
2899 int i;
2900 for (i=0; i<N; i++) {
2901 PackageParser.Provider p = pkg.providers.get(i);
2902 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2903 p.info.name));
2904 if (p.info.authority == null) {
2905
2906 /* The is another ContentProvider with this authority when
2907 * this app was installed so this authority is null,
2908 * Ignore it as we don't have to unregister the provider.
2909 */
2910 continue;
2911 }
2912 String names[] = p.info.authority.split(";");
2913 for (int j = 0; j < names.length; j++) {
2914 if (mProviders.get(names[j]) == p) {
2915 mProviders.remove(names[j]);
2916 if (chatty && Config.LOGD) Log.d(
2917 TAG, "Unregistered content provider: " + names[j] +
2918 ", className = " + p.info.name +
2919 ", isSyncable = " + p.info.isSyncable);
2920 }
2921 }
2922 if (chatty) {
2923 if (r == null) {
2924 r = new StringBuilder(256);
2925 } else {
2926 r.append(' ');
2927 }
2928 r.append(p.info.name);
2929 }
2930 }
2931 if (r != null) {
2932 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2933 }
2934
2935 N = pkg.services.size();
2936 r = null;
2937 for (i=0; i<N; i++) {
2938 PackageParser.Service s = pkg.services.get(i);
2939 mServices.removeService(s);
2940 if (chatty) {
2941 if (r == null) {
2942 r = new StringBuilder(256);
2943 } else {
2944 r.append(' ');
2945 }
2946 r.append(s.info.name);
2947 }
2948 }
2949 if (r != null) {
2950 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2951 }
2952
2953 N = pkg.receivers.size();
2954 r = null;
2955 for (i=0; i<N; i++) {
2956 PackageParser.Activity a = pkg.receivers.get(i);
2957 mReceivers.removeActivity(a, "receiver");
2958 if (chatty) {
2959 if (r == null) {
2960 r = new StringBuilder(256);
2961 } else {
2962 r.append(' ');
2963 }
2964 r.append(a.info.name);
2965 }
2966 }
2967 if (r != null) {
2968 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2969 }
2970
2971 N = pkg.activities.size();
2972 r = null;
2973 for (i=0; i<N; i++) {
2974 PackageParser.Activity a = pkg.activities.get(i);
2975 mActivities.removeActivity(a, "activity");
2976 if (chatty) {
2977 if (r == null) {
2978 r = new StringBuilder(256);
2979 } else {
2980 r.append(' ');
2981 }
2982 r.append(a.info.name);
2983 }
2984 }
2985 if (r != null) {
2986 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2987 }
2988
2989 N = pkg.permissions.size();
2990 r = null;
2991 for (i=0; i<N; i++) {
2992 PackageParser.Permission p = pkg.permissions.get(i);
2993 boolean tree = false;
2994 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2995 if (bp == null) {
2996 tree = true;
2997 bp = mSettings.mPermissionTrees.get(p.info.name);
2998 }
2999 if (bp != null && bp.perm == p) {
3000 if (bp.type != BasePermission.TYPE_BUILTIN) {
3001 if (tree) {
3002 mSettings.mPermissionTrees.remove(p.info.name);
3003 } else {
3004 mSettings.mPermissions.remove(p.info.name);
3005 }
3006 } else {
3007 bp.perm = null;
3008 }
3009 if (chatty) {
3010 if (r == null) {
3011 r = new StringBuilder(256);
3012 } else {
3013 r.append(' ');
3014 }
3015 r.append(p.info.name);
3016 }
3017 }
3018 }
3019 if (r != null) {
3020 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3021 }
3022
3023 N = pkg.instrumentation.size();
3024 r = null;
3025 for (i=0; i<N; i++) {
3026 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3027 mInstrumentation.remove(a.component);
3028 if (chatty) {
3029 if (r == null) {
3030 r = new StringBuilder(256);
3031 } else {
3032 r.append(' ');
3033 }
3034 r.append(a.info.name);
3035 }
3036 }
3037 if (r != null) {
3038 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3039 }
3040 }
3041 }
3042
3043 private static final boolean isPackageFilename(String name) {
3044 return name != null && name.endsWith(".apk");
3045 }
3046
3047 private void updatePermissionsLP() {
3048 // Make sure there are no dangling permission trees.
3049 Iterator<BasePermission> it = mSettings.mPermissionTrees
3050 .values().iterator();
3051 while (it.hasNext()) {
3052 BasePermission bp = it.next();
3053 if (bp.perm == null) {
3054 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3055 + " from package " + bp.sourcePackage);
3056 it.remove();
3057 }
3058 }
3059
3060 // Make sure all dynamic permissions have been assigned to a package,
3061 // and make sure there are no dangling permissions.
3062 it = mSettings.mPermissions.values().iterator();
3063 while (it.hasNext()) {
3064 BasePermission bp = it.next();
3065 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3066 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3067 + bp.name + " pkg=" + bp.sourcePackage
3068 + " info=" + bp.pendingInfo);
3069 if (bp.perm == null && bp.pendingInfo != null) {
3070 BasePermission tree = findPermissionTreeLP(bp.name);
3071 if (tree != null) {
3072 bp.perm = new PackageParser.Permission(tree.perm.owner,
3073 new PermissionInfo(bp.pendingInfo));
3074 bp.perm.info.packageName = tree.perm.info.packageName;
3075 bp.perm.info.name = bp.name;
3076 bp.uid = tree.uid;
3077 }
3078 }
3079 }
3080 if (bp.perm == null) {
3081 Log.w(TAG, "Removing dangling permission: " + bp.name
3082 + " from package " + bp.sourcePackage);
3083 it.remove();
3084 }
3085 }
3086
3087 // Now update the permissions for all packages, in particular
3088 // replace the granted permissions of the system packages.
3089 for (PackageParser.Package pkg : mPackages.values()) {
3090 grantPermissionsLP(pkg, false);
3091 }
3092 }
3093
3094 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3095 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3096 if (ps == null) {
3097 return;
3098 }
3099 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3100 boolean addedPermission = false;
3101
3102 if (replace) {
3103 ps.permissionsFixed = false;
3104 if (gp == ps) {
3105 gp.grantedPermissions.clear();
3106 gp.gids = mGlobalGids;
3107 }
3108 }
3109
3110 if (gp.gids == null) {
3111 gp.gids = mGlobalGids;
3112 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07003113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 final int N = pkg.requestedPermissions.size();
3115 for (int i=0; i<N; i++) {
3116 String name = pkg.requestedPermissions.get(i);
3117 BasePermission bp = mSettings.mPermissions.get(name);
3118 PackageParser.Permission p = bp != null ? bp.perm : null;
3119 if (false) {
3120 if (gp != ps) {
3121 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3122 + ": " + p);
3123 }
3124 }
3125 if (p != null) {
3126 final String perm = p.info.name;
3127 boolean allowed;
3128 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3129 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3130 allowed = true;
3131 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3132 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003133 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003135 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 == PackageManager.SIGNATURE_MATCH);
3137 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3138 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3139 // For updated system applications, the signatureOrSystem permission
3140 // is granted only if it had been defined by the original application.
3141 if ((pkg.applicationInfo.flags
3142 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3143 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3144 if(sysPs.grantedPermissions.contains(perm)) {
3145 allowed = true;
3146 } else {
3147 allowed = false;
3148 }
3149 } else {
3150 allowed = true;
3151 }
3152 }
3153 }
3154 } else {
3155 allowed = false;
3156 }
3157 if (false) {
3158 if (gp != ps) {
3159 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3160 }
3161 }
3162 if (allowed) {
3163 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3164 && ps.permissionsFixed) {
3165 // If this is an existing, non-system package, then
3166 // we can't add any new permissions to it.
3167 if (!gp.loadedPermissions.contains(perm)) {
3168 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003169 // Except... if this is a permission that was added
3170 // to the platform (note: need to only do this when
3171 // updating the platform).
3172 final int NP = PackageParser.NEW_PERMISSIONS.length;
3173 for (int ip=0; ip<NP; ip++) {
3174 final PackageParser.NewPermissionInfo npi
3175 = PackageParser.NEW_PERMISSIONS[ip];
3176 if (npi.name.equals(perm)
3177 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3178 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003179 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003180 + pkg.packageName);
3181 break;
3182 }
3183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 }
3185 }
3186 if (allowed) {
3187 if (!gp.grantedPermissions.contains(perm)) {
3188 addedPermission = true;
3189 gp.grantedPermissions.add(perm);
3190 gp.gids = appendInts(gp.gids, bp.gids);
3191 }
3192 } else {
3193 Log.w(TAG, "Not granting permission " + perm
3194 + " to package " + pkg.packageName
3195 + " because it was previously installed without");
3196 }
3197 } else {
3198 Log.w(TAG, "Not granting permission " + perm
3199 + " to package " + pkg.packageName
3200 + " (protectionLevel=" + p.info.protectionLevel
3201 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3202 + ")");
3203 }
3204 } else {
3205 Log.w(TAG, "Unknown permission " + name
3206 + " in package " + pkg.packageName);
3207 }
3208 }
3209
3210 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003211 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3212 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 // This is the first that we have heard about this package, so the
3214 // permissions we have now selected are fixed until explicitly
3215 // changed.
3216 ps.permissionsFixed = true;
3217 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3218 }
3219 }
3220
3221 private final class ActivityIntentResolver
3222 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003223 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003225 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 }
3227
Mihai Preda074edef2009-05-18 17:13:31 +02003228 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003230 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3232 }
3233
Mihai Predaeae850c2009-05-13 10:13:48 +02003234 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3235 ArrayList<PackageParser.Activity> packageActivities) {
3236 if (packageActivities == null) {
3237 return null;
3238 }
3239 mFlags = flags;
3240 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3241 int N = packageActivities.size();
3242 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3243 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003244
3245 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003246 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003247 intentFilters = packageActivities.get(i).intents;
3248 if (intentFilters != null && intentFilters.size() > 0) {
3249 listCut.add(intentFilters);
3250 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003251 }
3252 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3253 }
3254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 public final void addActivity(PackageParser.Activity a, String type) {
3256 mActivities.put(a.component, a);
3257 if (SHOW_INFO || Config.LOGV) Log.v(
3258 TAG, " " + type + " " +
3259 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3260 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3261 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003262 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3264 if (SHOW_INFO || Config.LOGV) {
3265 Log.v(TAG, " IntentFilter:");
3266 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3267 }
3268 if (!intent.debugCheck()) {
3269 Log.w(TAG, "==> For Activity " + a.info.name);
3270 }
3271 addFilter(intent);
3272 }
3273 }
3274
3275 public final void removeActivity(PackageParser.Activity a, String type) {
3276 mActivities.remove(a.component);
3277 if (SHOW_INFO || Config.LOGV) Log.v(
3278 TAG, " " + type + " " +
3279 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3280 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3281 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003282 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3284 if (SHOW_INFO || Config.LOGV) {
3285 Log.v(TAG, " IntentFilter:");
3286 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3287 }
3288 removeFilter(intent);
3289 }
3290 }
3291
3292 @Override
3293 protected boolean allowFilterResult(
3294 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3295 ActivityInfo filterAi = filter.activity.info;
3296 for (int i=dest.size()-1; i>=0; i--) {
3297 ActivityInfo destAi = dest.get(i).activityInfo;
3298 if (destAi.name == filterAi.name
3299 && destAi.packageName == filterAi.packageName) {
3300 return false;
3301 }
3302 }
3303 return true;
3304 }
3305
3306 @Override
3307 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3308 int match) {
3309 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3310 return null;
3311 }
3312 final PackageParser.Activity activity = info.activity;
3313 if (mSafeMode && (activity.info.applicationInfo.flags
3314 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3315 return null;
3316 }
3317 final ResolveInfo res = new ResolveInfo();
3318 res.activityInfo = PackageParser.generateActivityInfo(activity,
3319 mFlags);
3320 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3321 res.filter = info;
3322 }
3323 res.priority = info.getPriority();
3324 res.preferredOrder = activity.owner.mPreferredOrder;
3325 //System.out.println("Result: " + res.activityInfo.className +
3326 // " = " + res.priority);
3327 res.match = match;
3328 res.isDefault = info.hasDefault;
3329 res.labelRes = info.labelRes;
3330 res.nonLocalizedLabel = info.nonLocalizedLabel;
3331 res.icon = info.icon;
3332 return res;
3333 }
3334
3335 @Override
3336 protected void sortResults(List<ResolveInfo> results) {
3337 Collections.sort(results, mResolvePrioritySorter);
3338 }
3339
3340 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003341 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003343 out.print(prefix); out.print(
3344 Integer.toHexString(System.identityHashCode(filter.activity)));
3345 out.print(' ');
3346 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348
3349// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3350// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3351// final List<ResolveInfo> retList = Lists.newArrayList();
3352// while (i.hasNext()) {
3353// final ResolveInfo resolveInfo = i.next();
3354// if (isEnabledLP(resolveInfo.activityInfo)) {
3355// retList.add(resolveInfo);
3356// }
3357// }
3358// return retList;
3359// }
3360
3361 // Keys are String (activity class name), values are Activity.
3362 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3363 = new HashMap<ComponentName, PackageParser.Activity>();
3364 private int mFlags;
3365 }
3366
3367 private final class ServiceIntentResolver
3368 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003369 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003371 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 }
3373
Mihai Preda074edef2009-05-18 17:13:31 +02003374 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003376 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3378 }
3379
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003380 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3381 ArrayList<PackageParser.Service> packageServices) {
3382 if (packageServices == null) {
3383 return null;
3384 }
3385 mFlags = flags;
3386 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3387 int N = packageServices.size();
3388 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3389 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3390
3391 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3392 for (int i = 0; i < N; ++i) {
3393 intentFilters = packageServices.get(i).intents;
3394 if (intentFilters != null && intentFilters.size() > 0) {
3395 listCut.add(intentFilters);
3396 }
3397 }
3398 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3399 }
3400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 public final void addService(PackageParser.Service s) {
3402 mServices.put(s.component, s);
3403 if (SHOW_INFO || Config.LOGV) Log.v(
3404 TAG, " " + (s.info.nonLocalizedLabel != null
3405 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3406 if (SHOW_INFO || Config.LOGV) Log.v(
3407 TAG, " Class=" + s.info.name);
3408 int NI = s.intents.size();
3409 int j;
3410 for (j=0; j<NI; j++) {
3411 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3412 if (SHOW_INFO || Config.LOGV) {
3413 Log.v(TAG, " IntentFilter:");
3414 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3415 }
3416 if (!intent.debugCheck()) {
3417 Log.w(TAG, "==> For Service " + s.info.name);
3418 }
3419 addFilter(intent);
3420 }
3421 }
3422
3423 public final void removeService(PackageParser.Service s) {
3424 mServices.remove(s.component);
3425 if (SHOW_INFO || Config.LOGV) Log.v(
3426 TAG, " " + (s.info.nonLocalizedLabel != null
3427 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3428 if (SHOW_INFO || Config.LOGV) Log.v(
3429 TAG, " Class=" + s.info.name);
3430 int NI = s.intents.size();
3431 int j;
3432 for (j=0; j<NI; j++) {
3433 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3434 if (SHOW_INFO || Config.LOGV) {
3435 Log.v(TAG, " IntentFilter:");
3436 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3437 }
3438 removeFilter(intent);
3439 }
3440 }
3441
3442 @Override
3443 protected boolean allowFilterResult(
3444 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3445 ServiceInfo filterSi = filter.service.info;
3446 for (int i=dest.size()-1; i>=0; i--) {
3447 ServiceInfo destAi = dest.get(i).serviceInfo;
3448 if (destAi.name == filterSi.name
3449 && destAi.packageName == filterSi.packageName) {
3450 return false;
3451 }
3452 }
3453 return true;
3454 }
3455
3456 @Override
3457 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3458 int match) {
3459 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3460 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3461 return null;
3462 }
3463 final PackageParser.Service service = info.service;
3464 if (mSafeMode && (service.info.applicationInfo.flags
3465 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3466 return null;
3467 }
3468 final ResolveInfo res = new ResolveInfo();
3469 res.serviceInfo = PackageParser.generateServiceInfo(service,
3470 mFlags);
3471 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3472 res.filter = filter;
3473 }
3474 res.priority = info.getPriority();
3475 res.preferredOrder = service.owner.mPreferredOrder;
3476 //System.out.println("Result: " + res.activityInfo.className +
3477 // " = " + res.priority);
3478 res.match = match;
3479 res.isDefault = info.hasDefault;
3480 res.labelRes = info.labelRes;
3481 res.nonLocalizedLabel = info.nonLocalizedLabel;
3482 res.icon = info.icon;
3483 return res;
3484 }
3485
3486 @Override
3487 protected void sortResults(List<ResolveInfo> results) {
3488 Collections.sort(results, mResolvePrioritySorter);
3489 }
3490
3491 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003492 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003494 out.print(prefix); out.print(
3495 Integer.toHexString(System.identityHashCode(filter.service)));
3496 out.print(' ');
3497 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 }
3499
3500// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3501// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3502// final List<ResolveInfo> retList = Lists.newArrayList();
3503// while (i.hasNext()) {
3504// final ResolveInfo resolveInfo = (ResolveInfo) i;
3505// if (isEnabledLP(resolveInfo.serviceInfo)) {
3506// retList.add(resolveInfo);
3507// }
3508// }
3509// return retList;
3510// }
3511
3512 // Keys are String (activity class name), values are Activity.
3513 private final HashMap<ComponentName, PackageParser.Service> mServices
3514 = new HashMap<ComponentName, PackageParser.Service>();
3515 private int mFlags;
3516 };
3517
3518 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3519 new Comparator<ResolveInfo>() {
3520 public int compare(ResolveInfo r1, ResolveInfo r2) {
3521 int v1 = r1.priority;
3522 int v2 = r2.priority;
3523 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3524 if (v1 != v2) {
3525 return (v1 > v2) ? -1 : 1;
3526 }
3527 v1 = r1.preferredOrder;
3528 v2 = r2.preferredOrder;
3529 if (v1 != v2) {
3530 return (v1 > v2) ? -1 : 1;
3531 }
3532 if (r1.isDefault != r2.isDefault) {
3533 return r1.isDefault ? -1 : 1;
3534 }
3535 v1 = r1.match;
3536 v2 = r2.match;
3537 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3538 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3539 }
3540 };
3541
3542 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3543 new Comparator<ProviderInfo>() {
3544 public int compare(ProviderInfo p1, ProviderInfo p2) {
3545 final int v1 = p1.initOrder;
3546 final int v2 = p2.initOrder;
3547 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3548 }
3549 };
3550
3551 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3552 IActivityManager am = ActivityManagerNative.getDefault();
3553 if (am != null) {
3554 try {
3555 final Intent intent = new Intent(action,
3556 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3557 if (extras != null) {
3558 intent.putExtras(extras);
3559 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003560 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 am.broadcastIntent(
3562 null, intent,
3563 null, null, 0, null, null, null, false, false);
3564 } catch (RemoteException ex) {
3565 }
3566 }
3567 }
3568
3569 private final class AppDirObserver extends FileObserver {
3570 public AppDirObserver(String path, int mask, boolean isrom) {
3571 super(path, mask);
3572 mRootDir = path;
3573 mIsRom = isrom;
3574 }
3575
3576 public void onEvent(int event, String path) {
3577 String removedPackage = null;
3578 int removedUid = -1;
3579 String addedPackage = null;
3580 int addedUid = -1;
3581
3582 synchronized (mInstallLock) {
3583 String fullPathStr = null;
3584 File fullPath = null;
3585 if (path != null) {
3586 fullPath = new File(mRootDir, path);
3587 fullPathStr = fullPath.getPath();
3588 }
3589
3590 if (Config.LOGV) Log.v(
3591 TAG, "File " + fullPathStr + " changed: "
3592 + Integer.toHexString(event));
3593
3594 if (!isPackageFilename(path)) {
3595 if (Config.LOGV) Log.v(
3596 TAG, "Ignoring change of non-package file: " + fullPathStr);
3597 return;
3598 }
3599
3600 if ((event&REMOVE_EVENTS) != 0) {
3601 synchronized (mInstallLock) {
3602 PackageParser.Package p = mAppDirs.get(fullPathStr);
3603 if (p != null) {
3604 removePackageLI(p, true);
3605 removedPackage = p.applicationInfo.packageName;
3606 removedUid = p.applicationInfo.uid;
3607 }
3608 }
3609 }
3610
3611 if ((event&ADD_EVENTS) != 0) {
3612 PackageParser.Package p = mAppDirs.get(fullPathStr);
3613 if (p == null) {
3614 p = scanPackageLI(fullPath, fullPath, fullPath,
3615 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3616 PackageParser.PARSE_CHATTY |
3617 PackageParser.PARSE_MUST_BE_APK,
3618 SCAN_MONITOR);
3619 if (p != null) {
3620 synchronized (mPackages) {
3621 grantPermissionsLP(p, false);
3622 }
3623 addedPackage = p.applicationInfo.packageName;
3624 addedUid = p.applicationInfo.uid;
3625 }
3626 }
3627 }
3628
3629 synchronized (mPackages) {
3630 mSettings.writeLP();
3631 }
3632 }
3633
3634 if (removedPackage != null) {
3635 Bundle extras = new Bundle(1);
3636 extras.putInt(Intent.EXTRA_UID, removedUid);
3637 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3638 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3639 }
3640 if (addedPackage != null) {
3641 Bundle extras = new Bundle(1);
3642 extras.putInt(Intent.EXTRA_UID, addedUid);
3643 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3644 }
3645 }
3646
3647 private final String mRootDir;
3648 private final boolean mIsRom;
3649 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 /* Called when a downloaded package installation has been confirmed by the user */
3652 public void installPackage(
3653 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003654 installPackage(packageURI, observer, flags, null);
3655 }
3656
3657 /* Called when a downloaded package installation has been confirmed by the user */
3658 public void installPackage(
3659 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3660 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 mContext.enforceCallingOrSelfPermission(
3662 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 // Queue up an async operation since the package installation may take a little while.
3665 mHandler.post(new Runnable() {
3666 public void run() {
3667 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003668 // Result object to be returned
3669 PackageInstalledInfo res = new PackageInstalledInfo();
3670 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3671 res.uid = -1;
3672 res.pkg = null;
3673 res.removedInfo = new PackageRemovedInfo();
3674 // Make a temporary copy of file from given packageURI
3675 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3676 if (tmpPackageFile != null) {
3677 synchronized (mInstallLock) {
3678 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 }
3681 if (observer != null) {
3682 try {
3683 observer.packageInstalled(res.name, res.returnCode);
3684 } catch (RemoteException e) {
3685 Log.i(TAG, "Observer no longer exists.");
3686 }
3687 }
3688 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3689 // call appears in the synchronized block above.
3690 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3691 res.removedInfo.sendBroadcast(false, true);
3692 Bundle extras = new Bundle(1);
3693 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003694 final boolean update = res.removedInfo.removedPackage != null;
3695 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3697 }
3698 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3699 res.pkg.applicationInfo.packageName,
3700 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003701 if (update) {
3702 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3703 res.pkg.applicationInfo.packageName,
3704 extras);
3705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 }
3707 Runtime.getRuntime().gc();
3708 }
3709 });
3710 }
3711
3712 class PackageInstalledInfo {
3713 String name;
3714 int uid;
3715 PackageParser.Package pkg;
3716 int returnCode;
3717 PackageRemovedInfo removedInfo;
3718 }
3719
3720 /*
3721 * Install a non-existing package.
3722 */
3723 private void installNewPackageLI(String pkgName,
3724 File tmpPackageFile,
3725 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003726 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003727 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 // Remember this for later, in case we need to rollback this install
3729 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3730 res.name = pkgName;
3731 synchronized(mPackages) {
3732 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3733 // Don't allow installation over an existing package with the same name.
3734 Log.w(TAG, "Attempt to re-install " + pkgName
3735 + " without first uninstalling.");
3736 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3737 return;
3738 }
3739 }
3740 if (destPackageFile.exists()) {
3741 // It's safe to do this because we know (from the above check) that the file
3742 // isn't currently used for an installed package.
3743 destPackageFile.delete();
3744 }
3745 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3746 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3747 destResourceFile, pkg, 0,
3748 SCAN_MONITOR | SCAN_FORCE_DEX
3749 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003750 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3751 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 if (newPackage == null) {
3753 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3754 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3755 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3756 }
3757 } else {
3758 updateSettingsLI(pkgName, tmpPackageFile,
3759 destFilePath, destPackageFile,
3760 destResourceFile, pkg,
3761 newPackage,
3762 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003763 forwardLocked,
3764 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 res);
3766 // delete the partially installed application. the data directory will have to be
3767 // restored if it was already existing
3768 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3769 // remove package from internal structures. Note that we want deletePackageX to
3770 // delete the package data and cache directories that it created in
3771 // scanPackageLocked, unless those directories existed before we even tried to
3772 // install.
3773 deletePackageLI(
3774 pkgName, true,
3775 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3776 res.removedInfo);
3777 }
3778 }
3779 }
3780
3781 private void replacePackageLI(String pkgName,
3782 File tmpPackageFile,
3783 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003784 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003785 String installerPackageName, PackageInstalledInfo res) {
3786
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003787 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788 // First find the old package info and check signatures
3789 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003790 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003791 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3792 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3794 return;
3795 }
3796 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003797 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003799 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003801 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003802 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003804 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003805 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003806 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 }
3808 }
3809
3810 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3811 File tmpPackageFile,
3812 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003813 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003814 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 PackageParser.Package newPackage = null;
3816 String pkgName = deletedPackage.packageName;
3817 boolean deletedPkg = true;
3818 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003819
3820 String oldInstallerPackageName = null;
3821 synchronized (mPackages) {
3822 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3823 }
3824
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003825 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 // First delete the existing package while retaining the data directory
3827 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3828 res.removedInfo)) {
3829 // If the existing package was'nt successfully deleted
3830 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3831 deletedPkg = false;
3832 } else {
3833 // Successfully deleted the old package. Now proceed with re-installation
3834 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3835 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3836 destResourceFile, pkg, parseFlags,
3837 SCAN_MONITOR | SCAN_FORCE_DEX
3838 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003839 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3840 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 if (newPackage == null) {
3842 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3843 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3844 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3845 }
3846 } else {
3847 updateSettingsLI(pkgName, tmpPackageFile,
3848 destFilePath, destPackageFile,
3849 destResourceFile, pkg,
3850 newPackage,
3851 true,
3852 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003853 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 res);
3855 updatedSettings = true;
3856 }
3857 }
3858
3859 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3860 // If we deleted an exisiting package, the old source and resource files that we
3861 // were keeping around in case we needed them (see below) can now be deleted
3862 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3863 final ApplicationInfo installedPackageAppInfo =
3864 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003865 deletePackageResourcesLI(pkgName,
3866 !deletedPackageAppInfo.sourceDir
3867 .equals(installedPackageAppInfo.sourceDir)
3868 ? deletedPackageAppInfo.sourceDir : null,
3869 !deletedPackageAppInfo.publicSourceDir
3870 .equals(installedPackageAppInfo.publicSourceDir)
3871 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 //update signature on the new package setting
3873 //this should always succeed, since we checked the
3874 //signature earlier.
3875 synchronized(mPackages) {
3876 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3877 parseFlags, true);
3878 }
3879 } else {
3880 // remove package from internal structures. Note that we want deletePackageX to
3881 // delete the package data and cache directories that it created in
3882 // scanPackageLocked, unless those directories existed before we even tried to
3883 // install.
3884 if(updatedSettings) {
3885 deletePackageLI(
3886 pkgName, true,
3887 PackageManager.DONT_DELETE_DATA,
3888 res.removedInfo);
3889 }
3890 // Since we failed to install the new package we need to restore the old
3891 // package that we deleted.
3892 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003893 File restoreFile = new File(deletedPackage.mPath);
3894 if (restoreFile == null) {
3895 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
3896 return;
3897 }
3898 File restoreTmpFile = createTempPackageFile();
3899 if (restoreTmpFile == null) {
3900 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
3901 return;
3902 }
3903 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
3904 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
3905 return;
3906 }
3907 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
3908 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003909 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003910 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003911 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003912 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003913 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
3914 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3915 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
3916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 }
3918 }
3919 }
3920
3921 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3922 File tmpPackageFile,
3923 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003924 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003925 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 PackageParser.Package newPackage = null;
3927 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003928 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 PackageParser.PARSE_IS_SYSTEM;
3930 String packageName = deletedPackage.packageName;
3931 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3932 if (packageName == null) {
3933 Log.w(TAG, "Attempt to delete null packageName.");
3934 return;
3935 }
3936 PackageParser.Package oldPkg;
3937 PackageSetting oldPkgSetting;
3938 synchronized (mPackages) {
3939 oldPkg = mPackages.get(packageName);
3940 oldPkgSetting = mSettings.mPackages.get(packageName);
3941 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3942 (oldPkgSetting == null)) {
3943 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3944 return;
3945 }
3946 }
3947 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3948 res.removedInfo.removedPackage = packageName;
3949 // Remove existing system package
3950 removePackageLI(oldPkg, true);
3951 synchronized (mPackages) {
3952 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3953 }
3954
3955 // Successfully disabled the old package. Now proceed with re-installation
3956 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3957 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3958 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3959 destResourceFile, pkg, parseFlags,
3960 SCAN_MONITOR | SCAN_FORCE_DEX
3961 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003962 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3963 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 if (newPackage == null) {
3965 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3966 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3967 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3968 }
3969 } else {
3970 updateSettingsLI(packageName, tmpPackageFile,
3971 destFilePath, destPackageFile,
3972 destResourceFile, pkg,
3973 newPackage,
3974 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003975 forwardLocked,
3976 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 res);
3978 updatedSettings = true;
3979 }
3980
3981 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3982 //update signature on the new package setting
3983 //this should always succeed, since we checked the
3984 //signature earlier.
3985 synchronized(mPackages) {
3986 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3987 parseFlags, true);
3988 }
3989 } else {
3990 // Re installation failed. Restore old information
3991 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07003992 if (newPackage != null) {
3993 removePackageLI(newPackage, true);
3994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 // Add back the old system package
3996 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3997 oldPkgSetting.resourcePath,
3998 oldPkg, parseFlags,
3999 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004000 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 // Restore the old system information in Settings
4002 synchronized(mPackages) {
4003 if(updatedSettings) {
4004 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004005 mSettings.setInstallerPackageName(packageName,
4006 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 }
4008 mSettings.writeLP();
4009 }
4010 }
4011 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 private void updateSettingsLI(String pkgName, File tmpPackageFile,
4014 String destFilePath, File destPackageFile,
4015 File destResourceFile,
4016 PackageParser.Package pkg,
4017 PackageParser.Package newPackage,
4018 boolean replacingExistingPackage,
4019 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02004020 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 synchronized (mPackages) {
4022 //write settings. the installStatus will be incomplete at this stage.
4023 //note that the new package setting would have already been
4024 //added to mPackages. It hasn't been persisted yet.
4025 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4026 mSettings.writeLP();
4027 }
4028
4029 int retCode = 0;
4030 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4031 retCode = mInstaller.movedex(tmpPackageFile.toString(),
4032 destPackageFile.toString());
4033 if (retCode != 0) {
4034 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
4035 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4036 return;
4037 }
4038 }
4039 // XXX There are probably some big issues here: upon doing
4040 // the rename, we have reached the point of no return (the
4041 // original .apk is gone!), so we can't fail. Yet... we can.
4042 if (!tmpPackageFile.renameTo(destPackageFile)) {
4043 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
4044 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4045 } else {
4046 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4047 destResourceFile,
4048 forwardLocked);
4049 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4050 return;
4051 } else {
4052 Log.d(TAG, "New package installed in " + destPackageFile);
4053 }
4054 }
4055 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4056 if (mInstaller != null) {
4057 mInstaller.rmdex(tmpPackageFile.getPath());
4058 }
4059 }
4060
4061 synchronized (mPackages) {
4062 grantPermissionsLP(newPackage, true);
4063 res.name = pkgName;
4064 res.uid = newPackage.applicationInfo.uid;
4065 res.pkg = newPackage;
4066 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004067 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4069 //to update install status
4070 mSettings.writeLP();
4071 }
4072 }
4073
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004074 private File getFwdLockedResource(String pkgName) {
4075 final String publicZipFileName = pkgName + ".zip";
4076 return new File(mAppInstallDir, publicZipFileName);
4077 }
4078
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004079 private File copyTempInstallFile(Uri pPackageURI,
4080 PackageInstalledInfo res) {
4081 File tmpPackageFile = createTempPackageFile();
4082 int retCode = PackageManager.INSTALL_SUCCEEDED;
4083 if (tmpPackageFile == null) {
4084 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4085 return null;
4086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004088 if (pPackageURI.getScheme().equals("file")) {
4089 final File srcPackageFile = new File(pPackageURI.getPath());
4090 // We copy the source package file to a temp file and then rename it to the
4091 // destination file in order to eliminate a window where the package directory
4092 // scanner notices the new package file but it's not completely copied yet.
4093 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4094 Log.e(TAG, "Couldn't copy package file to temp file.");
4095 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004097 } else if (pPackageURI.getScheme().equals("content")) {
4098 ParcelFileDescriptor fd = null;
4099 try {
4100 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4101 } catch (FileNotFoundException e) {
4102 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4103 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4104 }
4105 if (fd == null) {
4106 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4107 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4108 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 if (Config.LOGV) {
4110 Log.v(TAG, "Opened file descriptor from download service.");
4111 }
4112 ParcelFileDescriptor.AutoCloseInputStream
4113 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4114 // We copy the source package file to a temp file and then rename it to the
4115 // destination file in order to eliminate a window where the package directory
4116 // scanner notices the new package file but it's not completely copied yet.
4117 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4118 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004119 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004122 } else {
4123 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4124 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4125 }
4126
4127 res.returnCode = retCode;
4128 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4129 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4130 tmpPackageFile.delete();
4131 }
4132 return null;
4133 }
4134 return tmpPackageFile;
4135 }
4136
4137 private void installPackageLI(Uri pPackageURI,
4138 int pFlags, boolean newInstall, String installerPackageName,
4139 File tmpPackageFile, PackageInstalledInfo res) {
4140 String pkgName = null;
4141 boolean forwardLocked = false;
4142 boolean replacingExistingPackage = false;
4143 // Result object to be returned
4144 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4145
4146 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 pkgName = PackageParser.parsePackageName(
4148 tmpPackageFile.getAbsolutePath(), 0);
4149 if (pkgName == null) {
4150 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4151 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4152 break main_flow;
4153 }
4154 res.name = pkgName;
4155 //initialize some variables before installing pkg
4156 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004157 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 ? mDrmAppPrivateInstallDir
4159 : mAppInstallDir;
4160 final File destPackageFile = new File(destDir, pkgFileName);
4161 final String destFilePath = destPackageFile.getAbsolutePath();
4162 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004163 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004164 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 forwardLocked = true;
4166 } else {
4167 destResourceFile = destPackageFile;
4168 }
4169 // Retrieve PackageSettings and parse package
4170 int parseFlags = PackageParser.PARSE_CHATTY;
4171 parseFlags |= mDefParseFlags;
4172 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4173 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4175 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4176 if (pkg == null) {
4177 res.returnCode = pp.getParseError();
4178 break main_flow;
4179 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004180 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4181 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4182 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4183 break main_flow;
4184 }
4185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4187 res.returnCode = pp.getParseError();
4188 break main_flow;
4189 }
4190
4191 synchronized (mPackages) {
4192 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004193 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 && mPackages.containsKey(pkgName)) {
4195 replacingExistingPackage = true;
4196 }
4197 }
4198
4199 if(replacingExistingPackage) {
4200 replacePackageLI(pkgName,
4201 tmpPackageFile,
4202 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004203 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 res);
4205 } else {
4206 installNewPackageLI(pkgName,
4207 tmpPackageFile,
4208 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004209 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004210 res);
4211 }
4212 } finally {
4213 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4214 tmpPackageFile.delete();
4215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 }
4217 }
4218
4219 private int setPermissionsLI(String pkgName,
4220 PackageParser.Package newPackage,
4221 String destFilePath,
4222 File destResourceFile,
4223 boolean forwardLocked) {
4224 int retCode;
4225 if (forwardLocked) {
4226 try {
4227 extractPublicFiles(newPackage, destResourceFile);
4228 } catch (IOException e) {
4229 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4230 " forward-locked app.");
4231 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4232 } finally {
4233 //TODO clean up the extracted public files
4234 }
4235 if (mInstaller != null) {
4236 retCode = mInstaller.setForwardLockPerm(pkgName,
4237 newPackage.applicationInfo.uid);
4238 } else {
4239 final int filePermissions =
4240 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4241 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4242 newPackage.applicationInfo.uid);
4243 }
4244 } else {
4245 final int filePermissions =
4246 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4247 |FileUtils.S_IROTH;
4248 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4249 }
4250 if (retCode != 0) {
4251 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4252 + ". The return code was: " + retCode);
4253 }
4254 return PackageManager.INSTALL_SUCCEEDED;
4255 }
4256
4257 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4258 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4259 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4260 }
4261
4262 private void extractPublicFiles(PackageParser.Package newPackage,
4263 File publicZipFile) throws IOException {
4264 final ZipOutputStream publicZipOutStream =
4265 new ZipOutputStream(new FileOutputStream(publicZipFile));
4266 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4267
4268 // Copy manifest, resources.arsc and res directory to public zip
4269
4270 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4271 while (privateZipEntries.hasMoreElements()) {
4272 final ZipEntry zipEntry = privateZipEntries.nextElement();
4273 final String zipEntryName = zipEntry.getName();
4274 if ("AndroidManifest.xml".equals(zipEntryName)
4275 || "resources.arsc".equals(zipEntryName)
4276 || zipEntryName.startsWith("res/")) {
4277 try {
4278 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4279 } catch (IOException e) {
4280 try {
4281 publicZipOutStream.close();
4282 throw e;
4283 } finally {
4284 publicZipFile.delete();
4285 }
4286 }
4287 }
4288 }
4289
4290 publicZipOutStream.close();
4291 FileUtils.setPermissions(
4292 publicZipFile.getAbsolutePath(),
4293 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4294 -1, -1);
4295 }
4296
4297 private static void copyZipEntry(ZipEntry zipEntry,
4298 ZipFile inZipFile,
4299 ZipOutputStream outZipStream) throws IOException {
4300 byte[] buffer = new byte[4096];
4301 int num;
4302
4303 ZipEntry newEntry;
4304 if (zipEntry.getMethod() == ZipEntry.STORED) {
4305 // Preserve the STORED method of the input entry.
4306 newEntry = new ZipEntry(zipEntry);
4307 } else {
4308 // Create a new entry so that the compressed len is recomputed.
4309 newEntry = new ZipEntry(zipEntry.getName());
4310 }
4311 outZipStream.putNextEntry(newEntry);
4312
4313 InputStream data = inZipFile.getInputStream(zipEntry);
4314 while ((num = data.read(buffer)) > 0) {
4315 outZipStream.write(buffer, 0, num);
4316 }
4317 outZipStream.flush();
4318 }
4319
4320 private void deleteTempPackageFiles() {
4321 FilenameFilter filter = new FilenameFilter() {
4322 public boolean accept(File dir, String name) {
4323 return name.startsWith("vmdl") && name.endsWith(".tmp");
4324 }
4325 };
4326 String tmpFilesList[] = mAppInstallDir.list(filter);
4327 if(tmpFilesList == null) {
4328 return;
4329 }
4330 for(int i = 0; i < tmpFilesList.length; i++) {
4331 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4332 tmpFile.delete();
4333 }
4334 }
4335
4336 private File createTempPackageFile() {
4337 File tmpPackageFile;
4338 try {
4339 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4340 } catch (IOException e) {
4341 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4342 return null;
4343 }
4344 try {
4345 FileUtils.setPermissions(
4346 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4347 -1, -1);
4348 } catch (IOException e) {
4349 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4350 return null;
4351 }
4352 return tmpPackageFile;
4353 }
4354
4355 public void deletePackage(final String packageName,
4356 final IPackageDeleteObserver observer,
4357 final int flags) {
4358 mContext.enforceCallingOrSelfPermission(
4359 android.Manifest.permission.DELETE_PACKAGES, null);
4360 // Queue up an async operation since the package deletion may take a little while.
4361 mHandler.post(new Runnable() {
4362 public void run() {
4363 mHandler.removeCallbacks(this);
4364 final boolean succeded = deletePackageX(packageName, true, true, flags);
4365 if (observer != null) {
4366 try {
4367 observer.packageDeleted(succeded);
4368 } catch (RemoteException e) {
4369 Log.i(TAG, "Observer no longer exists.");
4370 } //end catch
4371 } //end if
4372 } //end run
4373 });
4374 }
4375
4376 /**
4377 * This method is an internal method that could be get invoked either
4378 * to delete an installed package or to clean up a failed installation.
4379 * After deleting an installed package, a broadcast is sent to notify any
4380 * listeners that the package has been installed. For cleaning up a failed
4381 * installation, the broadcast is not necessary since the package's
4382 * installation wouldn't have sent the initial broadcast either
4383 * The key steps in deleting a package are
4384 * deleting the package information in internal structures like mPackages,
4385 * deleting the packages base directories through installd
4386 * updating mSettings to reflect current status
4387 * persisting settings for later use
4388 * sending a broadcast if necessary
4389 */
4390
4391 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4392 boolean deleteCodeAndResources, int flags) {
4393 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004394 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395
4396 synchronized (mInstallLock) {
4397 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4398 }
4399
4400 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004401 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4402 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4403
4404 // If the removed package was a system update, the old system packaged
4405 // was re-enabled; we need to broadcast this information
4406 if (systemUpdate) {
4407 Bundle extras = new Bundle(1);
4408 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4409 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4410
4411 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4412 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 }
4415 return res;
4416 }
4417
4418 static class PackageRemovedInfo {
4419 String removedPackage;
4420 int uid = -1;
4421 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004422 boolean isRemovedPackageSystemUpdate = false;
4423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 void sendBroadcast(boolean fullRemove, boolean replacing) {
4425 Bundle extras = new Bundle(1);
4426 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4427 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4428 if (replacing) {
4429 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4430 }
4431 if (removedPackage != null) {
4432 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4433 }
4434 if (removedUid >= 0) {
4435 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4436 }
4437 }
4438 }
4439
4440 /*
4441 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4442 * flag is not set, the data directory is removed as well.
4443 * make sure this flag is set for partially installed apps. If not its meaningless to
4444 * delete a partially installed application.
4445 */
4446 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4447 int flags) {
4448 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004449 if (outInfo != null) {
4450 outInfo.removedPackage = packageName;
4451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 removePackageLI(p, true);
4453 // Retrieve object to delete permissions for shared user later on
4454 PackageSetting deletedPs;
4455 synchronized (mPackages) {
4456 deletedPs = mSettings.mPackages.get(packageName);
4457 }
4458 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4459 if (mInstaller != null) {
4460 int retCode = mInstaller.remove(packageName);
4461 if (retCode < 0) {
4462 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4463 + packageName + ", retcode=" + retCode);
4464 // we don't consider this to be a failure of the core package deletion
4465 }
4466 } else {
4467 //for emulator
4468 PackageParser.Package pkg = mPackages.get(packageName);
4469 File dataDir = new File(pkg.applicationInfo.dataDir);
4470 dataDir.delete();
4471 }
4472 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004473 if (outInfo != null) {
4474 outInfo.removedUid = mSettings.removePackageLP(packageName);
4475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 }
4477 }
4478 synchronized (mPackages) {
4479 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4480 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004481 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 }
4483 // Save settings now
4484 mSettings.writeLP ();
4485 }
4486 }
4487
4488 /*
4489 * Tries to delete system package.
4490 */
4491 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004492 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 ApplicationInfo applicationInfo = p.applicationInfo;
4494 //applicable for non-partially installed applications only
4495 if (applicationInfo == null) {
4496 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4497 return false;
4498 }
4499 PackageSetting ps = null;
4500 // Confirm if the system package has been updated
4501 // An updated system app can be deleted. This will also have to restore
4502 // the system pkg from system partition
4503 synchronized (mPackages) {
4504 ps = mSettings.getDisabledSystemPkg(p.packageName);
4505 }
4506 if (ps == null) {
4507 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4508 return false;
4509 } else {
4510 Log.i(TAG, "Deleting system pkg from data partition");
4511 }
4512 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004513 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004514 boolean deleteCodeAndResources = false;
4515 if (ps.versionCode < p.mVersionCode) {
4516 // Delete code and resources for downgrades
4517 deleteCodeAndResources = true;
4518 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4519 flags &= ~PackageManager.DONT_DELETE_DATA;
4520 }
4521 } else {
4522 // Preserve data by setting flag
4523 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4524 flags |= PackageManager.DONT_DELETE_DATA;
4525 }
4526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4528 if (!ret) {
4529 return false;
4530 }
4531 synchronized (mPackages) {
4532 // Reinstate the old system package
4533 mSettings.enableSystemPackageLP(p.packageName);
4534 }
4535 // Install the system package
4536 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4537 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4538 SCAN_MONITOR);
4539
4540 if (newPkg == null) {
4541 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4542 return false;
4543 }
4544 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004545 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 mSettings.writeLP();
4547 }
4548 return true;
4549 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004550
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004551 private void deletePackageResourcesLI(String packageName,
4552 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004553 if (sourceDir != null) {
4554 File sourceFile = new File(sourceDir);
4555 if (!sourceFile.exists()) {
4556 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4557 }
4558 // Delete application's code and resources
4559 sourceFile.delete();
4560 if (mInstaller != null) {
4561 int retCode = mInstaller.rmdex(sourceFile.toString());
4562 if (retCode < 0) {
4563 Log.w(TAG, "Couldn't remove dex file for package: "
4564 + packageName + " at location "
4565 + sourceFile.toString() + ", retcode=" + retCode);
4566 // we don't consider this to be a failure of the core package deletion
4567 }
4568 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004569 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004570 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4571 final File publicSourceFile = new File(publicSourceDir);
4572 if (!publicSourceFile.exists()) {
4573 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4574 }
4575 if (publicSourceFile.exists()) {
4576 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004577 }
4578 }
4579 }
4580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4582 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4583 ApplicationInfo applicationInfo = p.applicationInfo;
4584 if (applicationInfo == null) {
4585 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4586 return false;
4587 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004588 if (outInfo != null) {
4589 outInfo.uid = applicationInfo.uid;
4590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591
4592 // Delete package data from internal structures and also remove data if flag is set
4593 removePackageDataLI(p, outInfo, flags);
4594
4595 // Delete application code and resources
4596 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004597 deletePackageResourcesLI(applicationInfo.packageName,
4598 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 }
4600 return true;
4601 }
4602
4603 /*
4604 * This method handles package deletion in general
4605 */
4606 private boolean deletePackageLI(String packageName,
4607 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4608 if (packageName == null) {
4609 Log.w(TAG, "Attempt to delete null packageName.");
4610 return false;
4611 }
4612 PackageParser.Package p;
4613 boolean dataOnly = false;
4614 synchronized (mPackages) {
4615 p = mPackages.get(packageName);
4616 if (p == null) {
4617 //this retrieves partially installed apps
4618 dataOnly = true;
4619 PackageSetting ps = mSettings.mPackages.get(packageName);
4620 if (ps == null) {
4621 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4622 return false;
4623 }
4624 p = ps.pkg;
4625 }
4626 }
4627 if (p == null) {
4628 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4629 return false;
4630 }
4631
4632 if (dataOnly) {
4633 // Delete application data first
4634 removePackageDataLI(p, outInfo, flags);
4635 return true;
4636 }
4637 // At this point the package should have ApplicationInfo associated with it
4638 if (p.applicationInfo == null) {
4639 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4640 return false;
4641 }
4642 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4643 Log.i(TAG, "Removing system package:"+p.packageName);
4644 // When an updated system application is deleted we delete the existing resources as well and
4645 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004646 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 }
4648 Log.i(TAG, "Removing non-system package:"+p.packageName);
4649 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4650 }
4651
4652 public void clearApplicationUserData(final String packageName,
4653 final IPackageDataObserver observer) {
4654 mContext.enforceCallingOrSelfPermission(
4655 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4656 // Queue up an async operation since the package deletion may take a little while.
4657 mHandler.post(new Runnable() {
4658 public void run() {
4659 mHandler.removeCallbacks(this);
4660 final boolean succeeded;
4661 synchronized (mInstallLock) {
4662 succeeded = clearApplicationUserDataLI(packageName);
4663 }
4664 if (succeeded) {
4665 // invoke DeviceStorageMonitor's update method to clear any notifications
4666 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4667 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4668 if (dsm != null) {
4669 dsm.updateMemory();
4670 }
4671 }
4672 if(observer != null) {
4673 try {
4674 observer.onRemoveCompleted(packageName, succeeded);
4675 } catch (RemoteException e) {
4676 Log.i(TAG, "Observer no longer exists.");
4677 }
4678 } //end if observer
4679 } //end run
4680 });
4681 }
4682
4683 private boolean clearApplicationUserDataLI(String packageName) {
4684 if (packageName == null) {
4685 Log.w(TAG, "Attempt to delete null packageName.");
4686 return false;
4687 }
4688 PackageParser.Package p;
4689 boolean dataOnly = false;
4690 synchronized (mPackages) {
4691 p = mPackages.get(packageName);
4692 if(p == null) {
4693 dataOnly = true;
4694 PackageSetting ps = mSettings.mPackages.get(packageName);
4695 if((ps == null) || (ps.pkg == null)) {
4696 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4697 return false;
4698 }
4699 p = ps.pkg;
4700 }
4701 }
4702 if(!dataOnly) {
4703 //need to check this only for fully installed applications
4704 if (p == null) {
4705 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4706 return false;
4707 }
4708 final ApplicationInfo applicationInfo = p.applicationInfo;
4709 if (applicationInfo == null) {
4710 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4711 return false;
4712 }
4713 }
4714 if (mInstaller != null) {
4715 int retCode = mInstaller.clearUserData(packageName);
4716 if (retCode < 0) {
4717 Log.w(TAG, "Couldn't remove cache files for package: "
4718 + packageName);
4719 return false;
4720 }
4721 }
4722 return true;
4723 }
4724
4725 public void deleteApplicationCacheFiles(final String packageName,
4726 final IPackageDataObserver observer) {
4727 mContext.enforceCallingOrSelfPermission(
4728 android.Manifest.permission.DELETE_CACHE_FILES, null);
4729 // Queue up an async operation since the package deletion may take a little while.
4730 mHandler.post(new Runnable() {
4731 public void run() {
4732 mHandler.removeCallbacks(this);
4733 final boolean succeded;
4734 synchronized (mInstallLock) {
4735 succeded = deleteApplicationCacheFilesLI(packageName);
4736 }
4737 if(observer != null) {
4738 try {
4739 observer.onRemoveCompleted(packageName, succeded);
4740 } catch (RemoteException e) {
4741 Log.i(TAG, "Observer no longer exists.");
4742 }
4743 } //end if observer
4744 } //end run
4745 });
4746 }
4747
4748 private boolean deleteApplicationCacheFilesLI(String packageName) {
4749 if (packageName == null) {
4750 Log.w(TAG, "Attempt to delete null packageName.");
4751 return false;
4752 }
4753 PackageParser.Package p;
4754 synchronized (mPackages) {
4755 p = mPackages.get(packageName);
4756 }
4757 if (p == null) {
4758 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4759 return false;
4760 }
4761 final ApplicationInfo applicationInfo = p.applicationInfo;
4762 if (applicationInfo == null) {
4763 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4764 return false;
4765 }
4766 if (mInstaller != null) {
4767 int retCode = mInstaller.deleteCacheFiles(packageName);
4768 if (retCode < 0) {
4769 Log.w(TAG, "Couldn't remove cache files for package: "
4770 + packageName);
4771 return false;
4772 }
4773 }
4774 return true;
4775 }
4776
4777 public void getPackageSizeInfo(final String packageName,
4778 final IPackageStatsObserver observer) {
4779 mContext.enforceCallingOrSelfPermission(
4780 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4781 // Queue up an async operation since the package deletion may take a little while.
4782 mHandler.post(new Runnable() {
4783 public void run() {
4784 mHandler.removeCallbacks(this);
4785 PackageStats lStats = new PackageStats(packageName);
4786 final boolean succeded;
4787 synchronized (mInstallLock) {
4788 succeded = getPackageSizeInfoLI(packageName, lStats);
4789 }
4790 if(observer != null) {
4791 try {
4792 observer.onGetStatsCompleted(lStats, succeded);
4793 } catch (RemoteException e) {
4794 Log.i(TAG, "Observer no longer exists.");
4795 }
4796 } //end if observer
4797 } //end run
4798 });
4799 }
4800
4801 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4802 if (packageName == null) {
4803 Log.w(TAG, "Attempt to get size of null packageName.");
4804 return false;
4805 }
4806 PackageParser.Package p;
4807 boolean dataOnly = false;
4808 synchronized (mPackages) {
4809 p = mPackages.get(packageName);
4810 if(p == null) {
4811 dataOnly = true;
4812 PackageSetting ps = mSettings.mPackages.get(packageName);
4813 if((ps == null) || (ps.pkg == null)) {
4814 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4815 return false;
4816 }
4817 p = ps.pkg;
4818 }
4819 }
4820 String publicSrcDir = null;
4821 if(!dataOnly) {
4822 final ApplicationInfo applicationInfo = p.applicationInfo;
4823 if (applicationInfo == null) {
4824 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4825 return false;
4826 }
4827 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4828 }
4829 if (mInstaller != null) {
4830 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4831 publicSrcDir, pStats);
4832 if (res < 0) {
4833 return false;
4834 } else {
4835 return true;
4836 }
4837 }
4838 return true;
4839 }
4840
4841
4842 public void addPackageToPreferred(String packageName) {
4843 mContext.enforceCallingOrSelfPermission(
4844 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4845
4846 synchronized (mPackages) {
4847 PackageParser.Package p = mPackages.get(packageName);
4848 if (p == null) {
4849 return;
4850 }
4851 PackageSetting ps = (PackageSetting)p.mExtras;
4852 if (ps != null) {
4853 mSettings.mPreferredPackages.remove(ps);
4854 mSettings.mPreferredPackages.add(0, ps);
4855 updatePreferredIndicesLP();
4856 mSettings.writeLP();
4857 }
4858 }
4859 }
4860
4861 public void removePackageFromPreferred(String packageName) {
4862 mContext.enforceCallingOrSelfPermission(
4863 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4864
4865 synchronized (mPackages) {
4866 PackageParser.Package p = mPackages.get(packageName);
4867 if (p == null) {
4868 return;
4869 }
4870 if (p.mPreferredOrder > 0) {
4871 PackageSetting ps = (PackageSetting)p.mExtras;
4872 if (ps != null) {
4873 mSettings.mPreferredPackages.remove(ps);
4874 p.mPreferredOrder = 0;
4875 updatePreferredIndicesLP();
4876 mSettings.writeLP();
4877 }
4878 }
4879 }
4880 }
4881
4882 private void updatePreferredIndicesLP() {
4883 final ArrayList<PackageSetting> pkgs
4884 = mSettings.mPreferredPackages;
4885 final int N = pkgs.size();
4886 for (int i=0; i<N; i++) {
4887 pkgs.get(i).pkg.mPreferredOrder = N - i;
4888 }
4889 }
4890
4891 public List<PackageInfo> getPreferredPackages(int flags) {
4892 synchronized (mPackages) {
4893 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4894 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4895 final int N = pref.size();
4896 for (int i=0; i<N; i++) {
4897 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4898 }
4899 return res;
4900 }
4901 }
4902
4903 public void addPreferredActivity(IntentFilter filter, int match,
4904 ComponentName[] set, ComponentName activity) {
4905 mContext.enforceCallingOrSelfPermission(
4906 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4907
4908 synchronized (mPackages) {
4909 Log.i(TAG, "Adding preferred activity " + activity + ":");
4910 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4911 mSettings.mPreferredActivities.addFilter(
4912 new PreferredActivity(filter, match, set, activity));
4913 mSettings.writeLP();
4914 }
4915 }
4916
Satish Sampath8dbe6122009-06-02 23:35:54 +01004917 public void replacePreferredActivity(IntentFilter filter, int match,
4918 ComponentName[] set, ComponentName activity) {
4919 mContext.enforceCallingOrSelfPermission(
4920 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4921 if (filter.countActions() != 1) {
4922 throw new IllegalArgumentException(
4923 "replacePreferredActivity expects filter to have only 1 action.");
4924 }
4925 if (filter.countCategories() != 1) {
4926 throw new IllegalArgumentException(
4927 "replacePreferredActivity expects filter to have only 1 category.");
4928 }
4929 if (filter.countDataAuthorities() != 0
4930 || filter.countDataPaths() != 0
4931 || filter.countDataSchemes() != 0
4932 || filter.countDataTypes() != 0) {
4933 throw new IllegalArgumentException(
4934 "replacePreferredActivity expects filter to have no data authorities, " +
4935 "paths, schemes or types.");
4936 }
4937 synchronized (mPackages) {
4938 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4939 String action = filter.getAction(0);
4940 String category = filter.getCategory(0);
4941 while (it.hasNext()) {
4942 PreferredActivity pa = it.next();
4943 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
4944 it.remove();
4945 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
4946 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4947 }
4948 }
4949 addPreferredActivity(filter, match, set, activity);
4950 }
4951 }
4952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 public void clearPackagePreferredActivities(String packageName) {
4954 mContext.enforceCallingOrSelfPermission(
4955 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4956
4957 synchronized (mPackages) {
4958 if (clearPackagePreferredActivitiesLP(packageName)) {
4959 mSettings.writeLP();
4960 }
4961 }
4962 }
4963
4964 boolean clearPackagePreferredActivitiesLP(String packageName) {
4965 boolean changed = false;
4966 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4967 while (it.hasNext()) {
4968 PreferredActivity pa = it.next();
4969 if (pa.mActivity.getPackageName().equals(packageName)) {
4970 it.remove();
4971 changed = true;
4972 }
4973 }
4974 return changed;
4975 }
4976
4977 public int getPreferredActivities(List<IntentFilter> outFilters,
4978 List<ComponentName> outActivities, String packageName) {
4979
4980 int num = 0;
4981 synchronized (mPackages) {
4982 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4983 while (it.hasNext()) {
4984 PreferredActivity pa = it.next();
4985 if (packageName == null
4986 || pa.mActivity.getPackageName().equals(packageName)) {
4987 if (outFilters != null) {
4988 outFilters.add(new IntentFilter(pa));
4989 }
4990 if (outActivities != null) {
4991 outActivities.add(pa.mActivity);
4992 }
4993 }
4994 }
4995 }
4996
4997 return num;
4998 }
4999
5000 public void setApplicationEnabledSetting(String appPackageName,
5001 int newState, int flags) {
5002 setEnabledSetting(appPackageName, null, newState, flags);
5003 }
5004
5005 public void setComponentEnabledSetting(ComponentName componentName,
5006 int newState, int flags) {
5007 setEnabledSetting(componentName.getPackageName(),
5008 componentName.getClassName(), newState, flags);
5009 }
5010
5011 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005012 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5014 || newState == COMPONENT_ENABLED_STATE_ENABLED
5015 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5016 throw new IllegalArgumentException("Invalid new component state: "
5017 + newState);
5018 }
5019 PackageSetting pkgSetting;
5020 final int uid = Binder.getCallingUid();
5021 final int permission = mContext.checkCallingPermission(
5022 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5023 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005024 boolean sendNow = false;
5025 boolean isApp = (className == null);
5026 String key = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 int packageUid = -1;
5028 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005029 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005031 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005033 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 }
5035 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005036 "Unknown component: " + packageName
5037 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 }
5039 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5040 throw new SecurityException(
5041 "Permission Denial: attempt to change component state from pid="
5042 + Binder.getCallingPid()
5043 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5044 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005045 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 // We're dealing with an application/package level state change
5047 pkgSetting.enabled = newState;
5048 } else {
5049 // We're dealing with a component level state change
5050 switch (newState) {
5051 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005052 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 break;
5054 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005055 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 break;
5057 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005058 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 break;
5060 default:
5061 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005062 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 }
5064 }
5065 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005066 packageUid = pkgSetting.userId;
5067 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5068 sendNow = true;
5069 // Purge entry from pending broadcast list if another one exists already
5070 // since we are sending one right away.
5071 if (mPendingBroadcasts.get(key) != null) {
5072 mPendingBroadcasts.remove(key);
5073 // Can ignore empty list since its handled in the handler anyway
5074 }
5075 } else {
5076 if (mPendingBroadcasts.get(key) == null) {
5077 mPendingBroadcasts.put(key, packageName);
5078 }
5079 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5080 // Schedule a message
5081 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5082 }
5083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 long callingId = Binder.clearCallingIdentity();
5087 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005088 if (sendNow) {
5089 sendPackageChangedBroadcast(packageName,
5090 (flags&PackageManager.DONT_KILL_APP) != 0, key, packageUid);
5091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 } finally {
5093 Binder.restoreCallingIdentity(callingId);
5094 }
5095 }
5096
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005097 private void sendPackageChangedBroadcast(String packageName,
5098 boolean killFlag, String componentName, int packageUid) {
5099 Bundle extras = new Bundle(2);
5100 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentName);
5101 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5102 extras.putInt(Intent.EXTRA_UID, packageUid);
5103 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
5104 }
5105
Jacek Surazski65e13172009-04-28 15:26:38 +02005106 public String getInstallerPackageName(String packageName) {
5107 synchronized (mPackages) {
5108 PackageSetting pkg = mSettings.mPackages.get(packageName);
5109 if (pkg == null) {
5110 throw new IllegalArgumentException("Unknown package: " + packageName);
5111 }
5112 return pkg.installerPackageName;
5113 }
5114 }
5115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 public int getApplicationEnabledSetting(String appPackageName) {
5117 synchronized (mPackages) {
5118 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5119 if (pkg == null) {
5120 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5121 }
5122 return pkg.enabled;
5123 }
5124 }
5125
5126 public int getComponentEnabledSetting(ComponentName componentName) {
5127 synchronized (mPackages) {
5128 final String packageNameStr = componentName.getPackageName();
5129 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5130 if (pkg == null) {
5131 throw new IllegalArgumentException("Unknown component: " + componentName);
5132 }
5133 final String classNameStr = componentName.getClassName();
5134 return pkg.currentEnabledStateLP(classNameStr);
5135 }
5136 }
5137
5138 public void enterSafeMode() {
5139 if (!mSystemReady) {
5140 mSafeMode = true;
5141 }
5142 }
5143
5144 public void systemReady() {
5145 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005146
5147 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005148 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005149 mContext.getContentResolver(),
5150 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005151 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005152 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005153 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 }
5156
5157 public boolean isSafeMode() {
5158 return mSafeMode;
5159 }
5160
5161 public boolean hasSystemUidErrors() {
5162 return mHasSystemUidErrors;
5163 }
5164
5165 static String arrayToString(int[] array) {
5166 StringBuffer buf = new StringBuffer(128);
5167 buf.append('[');
5168 if (array != null) {
5169 for (int i=0; i<array.length; i++) {
5170 if (i > 0) buf.append(", ");
5171 buf.append(array[i]);
5172 }
5173 }
5174 buf.append(']');
5175 return buf.toString();
5176 }
5177
5178 @Override
5179 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5180 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5181 != PackageManager.PERMISSION_GRANTED) {
5182 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5183 + Binder.getCallingPid()
5184 + ", uid=" + Binder.getCallingUid()
5185 + " without permission "
5186 + android.Manifest.permission.DUMP);
5187 return;
5188 }
5189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005190 synchronized (mPackages) {
5191 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005192 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 pw.println(" ");
5194 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005195 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 pw.println(" ");
5197 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005198 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 pw.println(" ");
5200 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005201 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 pw.println(" ");
5203 pw.println("Preferred Packages:");
5204 {
5205 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005206 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005207 }
5208 }
5209 pw.println(" ");
5210 pw.println("Permissions:");
5211 {
5212 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005213 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5214 pw.print(Integer.toHexString(System.identityHashCode(p)));
5215 pw.println("):");
5216 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5217 pw.print(" uid="); pw.print(p.uid);
5218 pw.print(" gids="); pw.print(arrayToString(p.gids));
5219 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 }
5221 }
5222 pw.println(" ");
5223 pw.println("Packages:");
5224 {
5225 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005226 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5227 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5228 pw.println("):");
5229 pw.print(" userId="); pw.print(ps.userId);
5230 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5231 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5232 pw.print(" pkg="); pw.println(ps.pkg);
5233 pw.print(" codePath="); pw.println(ps.codePathString);
5234 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005236 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005237 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005238 pw.print(" supportsScreens=[");
5239 boolean first = true;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005240 if ((ps.pkg.applicationInfo.flags &
5241 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005242 if (!first) pw.print(", ");
5243 first = false;
5244 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005245 }
5246 if ((ps.pkg.applicationInfo.flags &
5247 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005248 if (!first) pw.print(", ");
5249 first = false;
5250 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005251 }
5252 if ((ps.pkg.applicationInfo.flags &
5253 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005254 if (!first) pw.print(", ");
5255 first = false;
5256 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005257 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005258 if ((ps.pkg.applicationInfo.flags &
5259 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005260 if (!first) pw.print(", ");
5261 first = false;
5262 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005263 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005264 if ((ps.pkg.applicationInfo.flags &
5265 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5266 if (!first) pw.print(", ");
5267 first = false;
5268 pw.print("anyDensity");
5269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005271 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005272 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5273 pw.print(" signatures="); pw.println(ps.signatures);
5274 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5275 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5276 pw.print(" installStatus="); pw.print(ps.installStatus);
5277 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 if (ps.disabledComponents.size() > 0) {
5279 pw.println(" disabledComponents:");
5280 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005281 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 }
5283 }
5284 if (ps.enabledComponents.size() > 0) {
5285 pw.println(" enabledComponents:");
5286 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005287 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 }
5289 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005290 if (ps.grantedPermissions.size() > 0) {
5291 pw.println(" grantedPermissions:");
5292 for (String s : ps.grantedPermissions) {
5293 pw.print(" "); pw.println(s);
5294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005296 if (ps.loadedPermissions.size() > 0) {
5297 pw.println(" loadedPermissions:");
5298 for (String s : ps.loadedPermissions) {
5299 pw.print(" "); pw.println(s);
5300 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302 }
5303 }
5304 pw.println(" ");
5305 pw.println("Shared Users:");
5306 {
5307 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005308 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5309 pw.print(Integer.toHexString(System.identityHashCode(su)));
5310 pw.println("):");
5311 pw.print(" userId="); pw.print(su.userId);
5312 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005313 pw.println(" grantedPermissions:");
5314 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005315 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 }
5317 pw.println(" loadedPermissions:");
5318 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005319 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 }
5321 }
5322 }
5323 pw.println(" ");
5324 pw.println("Settings parse messages:");
5325 pw.println(mSettings.mReadMessages.toString());
5326 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005327
5328 synchronized (mProviders) {
5329 pw.println(" ");
5330 pw.println("Registered ContentProviders:");
5331 for (PackageParser.Provider p : mProviders.values()) {
5332 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5333 pw.println(p.toString());
5334 }
5335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005336 }
5337
5338 static final class BasePermission {
5339 final static int TYPE_NORMAL = 0;
5340 final static int TYPE_BUILTIN = 1;
5341 final static int TYPE_DYNAMIC = 2;
5342
5343 final String name;
5344 final String sourcePackage;
5345 final int type;
5346 PackageParser.Permission perm;
5347 PermissionInfo pendingInfo;
5348 int uid;
5349 int[] gids;
5350
5351 BasePermission(String _name, String _sourcePackage, int _type) {
5352 name = _name;
5353 sourcePackage = _sourcePackage;
5354 type = _type;
5355 }
5356 }
5357
5358 static class PackageSignatures {
5359 private Signature[] mSignatures;
5360
5361 PackageSignatures(Signature[] sigs) {
5362 assignSignatures(sigs);
5363 }
5364
5365 PackageSignatures() {
5366 }
5367
5368 void writeXml(XmlSerializer serializer, String tagName,
5369 ArrayList<Signature> pastSignatures) throws IOException {
5370 if (mSignatures == null) {
5371 return;
5372 }
5373 serializer.startTag(null, tagName);
5374 serializer.attribute(null, "count",
5375 Integer.toString(mSignatures.length));
5376 for (int i=0; i<mSignatures.length; i++) {
5377 serializer.startTag(null, "cert");
5378 final Signature sig = mSignatures[i];
5379 final int sigHash = sig.hashCode();
5380 final int numPast = pastSignatures.size();
5381 int j;
5382 for (j=0; j<numPast; j++) {
5383 Signature pastSig = pastSignatures.get(j);
5384 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5385 serializer.attribute(null, "index", Integer.toString(j));
5386 break;
5387 }
5388 }
5389 if (j >= numPast) {
5390 pastSignatures.add(sig);
5391 serializer.attribute(null, "index", Integer.toString(numPast));
5392 serializer.attribute(null, "key", sig.toCharsString());
5393 }
5394 serializer.endTag(null, "cert");
5395 }
5396 serializer.endTag(null, tagName);
5397 }
5398
5399 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5400 throws IOException, XmlPullParserException {
5401 String countStr = parser.getAttributeValue(null, "count");
5402 if (countStr == null) {
5403 reportSettingsProblem(Log.WARN,
5404 "Error in package manager settings: <signatures> has"
5405 + " no count at " + parser.getPositionDescription());
5406 XmlUtils.skipCurrentTag(parser);
5407 }
5408 final int count = Integer.parseInt(countStr);
5409 mSignatures = new Signature[count];
5410 int pos = 0;
5411
5412 int outerDepth = parser.getDepth();
5413 int type;
5414 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5415 && (type != XmlPullParser.END_TAG
5416 || parser.getDepth() > outerDepth)) {
5417 if (type == XmlPullParser.END_TAG
5418 || type == XmlPullParser.TEXT) {
5419 continue;
5420 }
5421
5422 String tagName = parser.getName();
5423 if (tagName.equals("cert")) {
5424 if (pos < count) {
5425 String index = parser.getAttributeValue(null, "index");
5426 if (index != null) {
5427 try {
5428 int idx = Integer.parseInt(index);
5429 String key = parser.getAttributeValue(null, "key");
5430 if (key == null) {
5431 if (idx >= 0 && idx < pastSignatures.size()) {
5432 Signature sig = pastSignatures.get(idx);
5433 if (sig != null) {
5434 mSignatures[pos] = pastSignatures.get(idx);
5435 pos++;
5436 } else {
5437 reportSettingsProblem(Log.WARN,
5438 "Error in package manager settings: <cert> "
5439 + "index " + index + " is not defined at "
5440 + parser.getPositionDescription());
5441 }
5442 } else {
5443 reportSettingsProblem(Log.WARN,
5444 "Error in package manager settings: <cert> "
5445 + "index " + index + " is out of bounds at "
5446 + parser.getPositionDescription());
5447 }
5448 } else {
5449 while (pastSignatures.size() <= idx) {
5450 pastSignatures.add(null);
5451 }
5452 Signature sig = new Signature(key);
5453 pastSignatures.set(idx, sig);
5454 mSignatures[pos] = sig;
5455 pos++;
5456 }
5457 } catch (NumberFormatException e) {
5458 reportSettingsProblem(Log.WARN,
5459 "Error in package manager settings: <cert> "
5460 + "index " + index + " is not a number at "
5461 + parser.getPositionDescription());
5462 }
5463 } else {
5464 reportSettingsProblem(Log.WARN,
5465 "Error in package manager settings: <cert> has"
5466 + " no index at " + parser.getPositionDescription());
5467 }
5468 } else {
5469 reportSettingsProblem(Log.WARN,
5470 "Error in package manager settings: too "
5471 + "many <cert> tags, expected " + count
5472 + " at " + parser.getPositionDescription());
5473 }
5474 } else {
5475 reportSettingsProblem(Log.WARN,
5476 "Unknown element under <cert>: "
5477 + parser.getName());
5478 }
5479 XmlUtils.skipCurrentTag(parser);
5480 }
5481
5482 if (pos < count) {
5483 // Should never happen -- there is an error in the written
5484 // settings -- but if it does we don't want to generate
5485 // a bad array.
5486 Signature[] newSigs = new Signature[pos];
5487 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5488 mSignatures = newSigs;
5489 }
5490 }
5491
5492 /**
5493 * If any of the given 'sigs' is contained in the existing signatures,
5494 * then completely replace the current signatures with the ones in
5495 * 'sigs'. This is used for updating an existing package to a newly
5496 * installed version.
5497 */
5498 boolean updateSignatures(Signature[] sigs, boolean update) {
5499 if (mSignatures == null) {
5500 if (update) {
5501 assignSignatures(sigs);
5502 }
5503 return true;
5504 }
5505 if (sigs == null) {
5506 return false;
5507 }
5508
5509 for (int i=0; i<sigs.length; i++) {
5510 Signature sig = sigs[i];
5511 for (int j=0; j<mSignatures.length; j++) {
5512 if (mSignatures[j].equals(sig)) {
5513 if (update) {
5514 assignSignatures(sigs);
5515 }
5516 return true;
5517 }
5518 }
5519 }
5520 return false;
5521 }
5522
5523 /**
5524 * If any of the given 'sigs' is contained in the existing signatures,
5525 * then add in any new signatures found in 'sigs'. This is used for
5526 * including a new package into an existing shared user id.
5527 */
5528 boolean mergeSignatures(Signature[] sigs, boolean update) {
5529 if (mSignatures == null) {
5530 if (update) {
5531 assignSignatures(sigs);
5532 }
5533 return true;
5534 }
5535 if (sigs == null) {
5536 return false;
5537 }
5538
5539 Signature[] added = null;
5540 int addedCount = 0;
5541 boolean haveMatch = false;
5542 for (int i=0; i<sigs.length; i++) {
5543 Signature sig = sigs[i];
5544 boolean found = false;
5545 for (int j=0; j<mSignatures.length; j++) {
5546 if (mSignatures[j].equals(sig)) {
5547 found = true;
5548 haveMatch = true;
5549 break;
5550 }
5551 }
5552
5553 if (!found) {
5554 if (added == null) {
5555 added = new Signature[sigs.length];
5556 }
5557 added[i] = sig;
5558 addedCount++;
5559 }
5560 }
5561
5562 if (!haveMatch) {
5563 // Nothing matched -- reject the new signatures.
5564 return false;
5565 }
5566 if (added == null) {
5567 // Completely matched -- nothing else to do.
5568 return true;
5569 }
5570
5571 // Add additional signatures in.
5572 if (update) {
5573 Signature[] total = new Signature[addedCount+mSignatures.length];
5574 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5575 int j = mSignatures.length;
5576 for (int i=0; i<added.length; i++) {
5577 if (added[i] != null) {
5578 total[j] = added[i];
5579 j++;
5580 }
5581 }
5582 mSignatures = total;
5583 }
5584 return true;
5585 }
5586
5587 private void assignSignatures(Signature[] sigs) {
5588 if (sigs == null) {
5589 mSignatures = null;
5590 return;
5591 }
5592 mSignatures = new Signature[sigs.length];
5593 for (int i=0; i<sigs.length; i++) {
5594 mSignatures[i] = sigs[i];
5595 }
5596 }
5597
5598 @Override
5599 public String toString() {
5600 StringBuffer buf = new StringBuffer(128);
5601 buf.append("PackageSignatures{");
5602 buf.append(Integer.toHexString(System.identityHashCode(this)));
5603 buf.append(" [");
5604 if (mSignatures != null) {
5605 for (int i=0; i<mSignatures.length; i++) {
5606 if (i > 0) buf.append(", ");
5607 buf.append(Integer.toHexString(
5608 System.identityHashCode(mSignatures[i])));
5609 }
5610 }
5611 buf.append("]}");
5612 return buf.toString();
5613 }
5614 }
5615
5616 static class PreferredActivity extends IntentFilter {
5617 final int mMatch;
5618 final String[] mSetPackages;
5619 final String[] mSetClasses;
5620 final String[] mSetComponents;
5621 final ComponentName mActivity;
5622 final String mShortActivity;
5623 String mParseError;
5624
5625 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5626 ComponentName activity) {
5627 super(filter);
5628 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5629 mActivity = activity;
5630 mShortActivity = activity.flattenToShortString();
5631 mParseError = null;
5632 if (set != null) {
5633 final int N = set.length;
5634 String[] myPackages = new String[N];
5635 String[] myClasses = new String[N];
5636 String[] myComponents = new String[N];
5637 for (int i=0; i<N; i++) {
5638 ComponentName cn = set[i];
5639 if (cn == null) {
5640 mSetPackages = null;
5641 mSetClasses = null;
5642 mSetComponents = null;
5643 return;
5644 }
5645 myPackages[i] = cn.getPackageName().intern();
5646 myClasses[i] = cn.getClassName().intern();
5647 myComponents[i] = cn.flattenToShortString().intern();
5648 }
5649 mSetPackages = myPackages;
5650 mSetClasses = myClasses;
5651 mSetComponents = myComponents;
5652 } else {
5653 mSetPackages = null;
5654 mSetClasses = null;
5655 mSetComponents = null;
5656 }
5657 }
5658
5659 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5660 IOException {
5661 mShortActivity = parser.getAttributeValue(null, "name");
5662 mActivity = ComponentName.unflattenFromString(mShortActivity);
5663 if (mActivity == null) {
5664 mParseError = "Bad activity name " + mShortActivity;
5665 }
5666 String matchStr = parser.getAttributeValue(null, "match");
5667 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5668 String setCountStr = parser.getAttributeValue(null, "set");
5669 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5670
5671 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5672 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5673 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5674
5675 int setPos = 0;
5676
5677 int outerDepth = parser.getDepth();
5678 int type;
5679 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5680 && (type != XmlPullParser.END_TAG
5681 || parser.getDepth() > outerDepth)) {
5682 if (type == XmlPullParser.END_TAG
5683 || type == XmlPullParser.TEXT) {
5684 continue;
5685 }
5686
5687 String tagName = parser.getName();
5688 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5689 // + parser.getDepth() + " tag=" + tagName);
5690 if (tagName.equals("set")) {
5691 String name = parser.getAttributeValue(null, "name");
5692 if (name == null) {
5693 if (mParseError == null) {
5694 mParseError = "No name in set tag in preferred activity "
5695 + mShortActivity;
5696 }
5697 } else if (setPos >= setCount) {
5698 if (mParseError == null) {
5699 mParseError = "Too many set tags in preferred activity "
5700 + mShortActivity;
5701 }
5702 } else {
5703 ComponentName cn = ComponentName.unflattenFromString(name);
5704 if (cn == null) {
5705 if (mParseError == null) {
5706 mParseError = "Bad set name " + name + " in preferred activity "
5707 + mShortActivity;
5708 }
5709 } else {
5710 myPackages[setPos] = cn.getPackageName();
5711 myClasses[setPos] = cn.getClassName();
5712 myComponents[setPos] = name;
5713 setPos++;
5714 }
5715 }
5716 XmlUtils.skipCurrentTag(parser);
5717 } else if (tagName.equals("filter")) {
5718 //Log.i(TAG, "Starting to parse filter...");
5719 readFromXml(parser);
5720 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5721 // + parser.getDepth() + " tag=" + parser.getName());
5722 } else {
5723 reportSettingsProblem(Log.WARN,
5724 "Unknown element under <preferred-activities>: "
5725 + parser.getName());
5726 XmlUtils.skipCurrentTag(parser);
5727 }
5728 }
5729
5730 if (setPos != setCount) {
5731 if (mParseError == null) {
5732 mParseError = "Not enough set tags (expected " + setCount
5733 + " but found " + setPos + ") in " + mShortActivity;
5734 }
5735 }
5736
5737 mSetPackages = myPackages;
5738 mSetClasses = myClasses;
5739 mSetComponents = myComponents;
5740 }
5741
5742 public void writeToXml(XmlSerializer serializer) throws IOException {
5743 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5744 serializer.attribute(null, "name", mShortActivity);
5745 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5746 serializer.attribute(null, "set", Integer.toString(NS));
5747 for (int s=0; s<NS; s++) {
5748 serializer.startTag(null, "set");
5749 serializer.attribute(null, "name", mSetComponents[s]);
5750 serializer.endTag(null, "set");
5751 }
5752 serializer.startTag(null, "filter");
5753 super.writeToXml(serializer);
5754 serializer.endTag(null, "filter");
5755 }
5756
5757 boolean sameSet(List<ResolveInfo> query, int priority) {
5758 if (mSetPackages == null) return false;
5759 final int NQ = query.size();
5760 final int NS = mSetPackages.length;
5761 int numMatch = 0;
5762 for (int i=0; i<NQ; i++) {
5763 ResolveInfo ri = query.get(i);
5764 if (ri.priority != priority) continue;
5765 ActivityInfo ai = ri.activityInfo;
5766 boolean good = false;
5767 for (int j=0; j<NS; j++) {
5768 if (mSetPackages[j].equals(ai.packageName)
5769 && mSetClasses[j].equals(ai.name)) {
5770 numMatch++;
5771 good = true;
5772 break;
5773 }
5774 }
5775 if (!good) return false;
5776 }
5777 return numMatch == NS;
5778 }
5779 }
5780
5781 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005782 int pkgFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783
5784 HashSet<String> grantedPermissions = new HashSet<String>();
5785 int[] gids;
5786
5787 HashSet<String> loadedPermissions = new HashSet<String>();
5788
5789 GrantedPermissions(int pkgFlags) {
5790 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5791 }
5792 }
5793
5794 /**
5795 * Settings base class for pending and resolved classes.
5796 */
5797 static class PackageSettingBase extends GrantedPermissions {
5798 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005799 File codePath;
5800 String codePathString;
5801 File resourcePath;
5802 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 private long timeStamp;
5804 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005805 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806
5807 PackageSignatures signatures = new PackageSignatures();
5808
5809 boolean permissionsFixed;
5810
5811 /* Explicitly disabled components */
5812 HashSet<String> disabledComponents = new HashSet<String>(0);
5813 /* Explicitly enabled components */
5814 HashSet<String> enabledComponents = new HashSet<String>(0);
5815 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5816 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005817
5818 /* package name of the app that installed this package */
5819 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820
5821 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005822 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 super(pkgFlags);
5824 this.name = name;
5825 this.codePath = codePath;
5826 this.codePathString = codePath.toString();
5827 this.resourcePath = resourcePath;
5828 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005829 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 }
5831
Jacek Surazski65e13172009-04-28 15:26:38 +02005832 public void setInstallerPackageName(String packageName) {
5833 installerPackageName = packageName;
5834 }
5835
5836 String getInstallerPackageName() {
5837 return installerPackageName;
5838 }
5839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 public void setInstallStatus(int newStatus) {
5841 installStatus = newStatus;
5842 }
5843
5844 public int getInstallStatus() {
5845 return installStatus;
5846 }
5847
5848 public void setTimeStamp(long newStamp) {
5849 if (newStamp != timeStamp) {
5850 timeStamp = newStamp;
5851 timeStampString = Long.toString(newStamp);
5852 }
5853 }
5854
5855 public void setTimeStamp(long newStamp, String newStampStr) {
5856 timeStamp = newStamp;
5857 timeStampString = newStampStr;
5858 }
5859
5860 public long getTimeStamp() {
5861 return timeStamp;
5862 }
5863
5864 public String getTimeStampStr() {
5865 return timeStampString;
5866 }
5867
5868 public void copyFrom(PackageSettingBase base) {
5869 grantedPermissions = base.grantedPermissions;
5870 gids = base.gids;
5871 loadedPermissions = base.loadedPermissions;
5872
5873 timeStamp = base.timeStamp;
5874 timeStampString = base.timeStampString;
5875 signatures = base.signatures;
5876 permissionsFixed = base.permissionsFixed;
5877 disabledComponents = base.disabledComponents;
5878 enabledComponents = base.enabledComponents;
5879 enabled = base.enabled;
5880 installStatus = base.installStatus;
5881 }
5882
5883 void enableComponentLP(String componentClassName) {
5884 disabledComponents.remove(componentClassName);
5885 enabledComponents.add(componentClassName);
5886 }
5887
5888 void disableComponentLP(String componentClassName) {
5889 enabledComponents.remove(componentClassName);
5890 disabledComponents.add(componentClassName);
5891 }
5892
5893 void restoreComponentLP(String componentClassName) {
5894 enabledComponents.remove(componentClassName);
5895 disabledComponents.remove(componentClassName);
5896 }
5897
5898 int currentEnabledStateLP(String componentName) {
5899 if (enabledComponents.contains(componentName)) {
5900 return COMPONENT_ENABLED_STATE_ENABLED;
5901 } else if (disabledComponents.contains(componentName)) {
5902 return COMPONENT_ENABLED_STATE_DISABLED;
5903 } else {
5904 return COMPONENT_ENABLED_STATE_DEFAULT;
5905 }
5906 }
5907 }
5908
5909 /**
5910 * Settings data for a particular package we know about.
5911 */
5912 static final class PackageSetting extends PackageSettingBase {
5913 int userId;
5914 PackageParser.Package pkg;
5915 SharedUserSetting sharedUser;
5916
5917 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005918 int pVersionCode, int pkgFlags) {
5919 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 }
5921
5922 @Override
5923 public String toString() {
5924 return "PackageSetting{"
5925 + Integer.toHexString(System.identityHashCode(this))
5926 + " " + name + "/" + userId + "}";
5927 }
5928 }
5929
5930 /**
5931 * Settings data for a particular shared user ID we know about.
5932 */
5933 static final class SharedUserSetting extends GrantedPermissions {
5934 final String name;
5935 int userId;
5936 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5937 final PackageSignatures signatures = new PackageSignatures();
5938
5939 SharedUserSetting(String _name, int _pkgFlags) {
5940 super(_pkgFlags);
5941 name = _name;
5942 }
5943
5944 @Override
5945 public String toString() {
5946 return "SharedUserSetting{"
5947 + Integer.toHexString(System.identityHashCode(this))
5948 + " " + name + "/" + userId + "}";
5949 }
5950 }
5951
5952 /**
5953 * Holds information about dynamic settings.
5954 */
5955 private static final class Settings {
5956 private final File mSettingsFilename;
5957 private final File mBackupSettingsFilename;
5958 private final HashMap<String, PackageSetting> mPackages =
5959 new HashMap<String, PackageSetting>();
5960 // The user's preferred packages/applications, in order of preference.
5961 // First is the most preferred.
5962 private final ArrayList<PackageSetting> mPreferredPackages =
5963 new ArrayList<PackageSetting>();
5964 // List of replaced system applications
5965 final HashMap<String, PackageSetting> mDisabledSysPackages =
5966 new HashMap<String, PackageSetting>();
5967
5968 // The user's preferred activities associated with particular intent
5969 // filters.
5970 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5971 new IntentResolver<PreferredActivity, PreferredActivity>() {
5972 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005973 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005975 out.print(prefix); out.print(
5976 Integer.toHexString(System.identityHashCode(filter)));
5977 out.print(' ');
5978 out.print(filter.mActivity.flattenToShortString());
5979 out.print(" match=0x");
5980 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005982 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005983 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005984 out.print(prefix); out.print(" ");
5985 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 }
5987 }
5988 }
5989 };
5990 private final HashMap<String, SharedUserSetting> mSharedUsers =
5991 new HashMap<String, SharedUserSetting>();
5992 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5993 private final SparseArray<Object> mOtherUserIds =
5994 new SparseArray<Object>();
5995
5996 // For reading/writing settings file.
5997 private final ArrayList<Signature> mPastSignatures =
5998 new ArrayList<Signature>();
5999
6000 // Mapping from permission names to info about them.
6001 final HashMap<String, BasePermission> mPermissions =
6002 new HashMap<String, BasePermission>();
6003
6004 // Mapping from permission tree names to info about them.
6005 final HashMap<String, BasePermission> mPermissionTrees =
6006 new HashMap<String, BasePermission>();
6007
6008 private final ArrayList<String> mPendingPreferredPackages
6009 = new ArrayList<String>();
6010
6011 private final StringBuilder mReadMessages = new StringBuilder();
6012
6013 private static final class PendingPackage extends PackageSettingBase {
6014 final int sharedId;
6015
6016 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006017 int sharedId, int pVersionCode, int pkgFlags) {
6018 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 this.sharedId = sharedId;
6020 }
6021 }
6022 private final ArrayList<PendingPackage> mPendingPackages
6023 = new ArrayList<PendingPackage>();
6024
6025 Settings() {
6026 File dataDir = Environment.getDataDirectory();
6027 File systemDir = new File(dataDir, "system");
6028 systemDir.mkdirs();
6029 FileUtils.setPermissions(systemDir.toString(),
6030 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6031 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6032 -1, -1);
6033 mSettingsFilename = new File(systemDir, "packages.xml");
6034 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6035 }
6036
6037 PackageSetting getPackageLP(PackageParser.Package pkg,
6038 SharedUserSetting sharedUser, File codePath, File resourcePath,
6039 int pkgFlags, boolean create, boolean add) {
6040 final String name = pkg.packageName;
6041 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006042 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 return p;
6044 }
6045
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006046 PackageSetting peekPackageLP(String name) {
6047 return mPackages.get(name);
6048 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 PackageSetting p = mPackages.get(name);
6050 if (p != null && p.codePath.getPath().equals(codePath)) {
6051 return p;
6052 }
6053 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006054 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006055 }
6056
6057 void setInstallStatus(String pkgName, int status) {
6058 PackageSetting p = mPackages.get(pkgName);
6059 if(p != null) {
6060 if(p.getInstallStatus() != status) {
6061 p.setInstallStatus(status);
6062 }
6063 }
6064 }
6065
Jacek Surazski65e13172009-04-28 15:26:38 +02006066 void setInstallerPackageName(String pkgName,
6067 String installerPkgName) {
6068 PackageSetting p = mPackages.get(pkgName);
6069 if(p != null) {
6070 p.setInstallerPackageName(installerPkgName);
6071 }
6072 }
6073
6074 String getInstallerPackageName(String pkgName) {
6075 PackageSetting p = mPackages.get(pkgName);
6076 return (p == null) ? null : p.getInstallerPackageName();
6077 }
6078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 int getInstallStatus(String pkgName) {
6080 PackageSetting p = mPackages.get(pkgName);
6081 if(p != null) {
6082 return p.getInstallStatus();
6083 }
6084 return -1;
6085 }
6086
6087 SharedUserSetting getSharedUserLP(String name,
6088 int pkgFlags, boolean create) {
6089 SharedUserSetting s = mSharedUsers.get(name);
6090 if (s == null) {
6091 if (!create) {
6092 return null;
6093 }
6094 s = new SharedUserSetting(name, pkgFlags);
6095 if (MULTIPLE_APPLICATION_UIDS) {
6096 s.userId = newUserIdLP(s);
6097 } else {
6098 s.userId = FIRST_APPLICATION_UID;
6099 }
6100 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6101 // < 0 means we couldn't assign a userid; fall out and return
6102 // s, which is currently null
6103 if (s.userId >= 0) {
6104 mSharedUsers.put(name, s);
6105 }
6106 }
6107
6108 return s;
6109 }
6110
6111 int disableSystemPackageLP(String name) {
6112 PackageSetting p = mPackages.get(name);
6113 if(p == null) {
6114 Log.w(TAG, "Package:"+name+" is not an installed package");
6115 return -1;
6116 }
6117 PackageSetting dp = mDisabledSysPackages.get(name);
6118 // always make sure the system package code and resource paths dont change
6119 if(dp == null) {
6120 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6121 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6122 }
6123 mDisabledSysPackages.put(name, p);
6124 }
6125 return removePackageLP(name);
6126 }
6127
6128 PackageSetting enableSystemPackageLP(String name) {
6129 PackageSetting p = mDisabledSysPackages.get(name);
6130 if(p == null) {
6131 Log.w(TAG, "Package:"+name+" is not disabled");
6132 return null;
6133 }
6134 // Reset flag in ApplicationInfo object
6135 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6136 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6137 }
6138 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006139 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 mDisabledSysPackages.remove(name);
6141 return ret;
6142 }
6143
6144 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006145 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006146 PackageSetting p = mPackages.get(name);
6147 if (p != null) {
6148 if (p.userId == uid) {
6149 return p;
6150 }
6151 reportSettingsProblem(Log.ERROR,
6152 "Adding duplicate package, keeping first: " + name);
6153 return null;
6154 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006155 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 p.userId = uid;
6157 if (addUserIdLP(uid, p, name)) {
6158 mPackages.put(name, p);
6159 return p;
6160 }
6161 return null;
6162 }
6163
6164 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6165 SharedUserSetting s = mSharedUsers.get(name);
6166 if (s != null) {
6167 if (s.userId == uid) {
6168 return s;
6169 }
6170 reportSettingsProblem(Log.ERROR,
6171 "Adding duplicate shared user, keeping first: " + name);
6172 return null;
6173 }
6174 s = new SharedUserSetting(name, pkgFlags);
6175 s.userId = uid;
6176 if (addUserIdLP(uid, s, name)) {
6177 mSharedUsers.put(name, s);
6178 return s;
6179 }
6180 return null;
6181 }
6182
6183 private PackageSetting getPackageLP(String name,
6184 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006185 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 PackageSetting p = mPackages.get(name);
6187 if (p != null) {
6188 if (!p.codePath.equals(codePath)) {
6189 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006190 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006191 // This is an updated system app with versions in both system
6192 // and data partition. Just let the most recent version
6193 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006194 Log.w(TAG, "Trying to update system app code path from " +
6195 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006196 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006197 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006198 reportSettingsProblem(Log.WARN,
6199 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006200 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006202 }
6203 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 reportSettingsProblem(Log.WARN,
6205 "Package " + name + " shared user changed from "
6206 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6207 + " to "
6208 + (sharedUser != null ? sharedUser.name : "<nothing>")
6209 + "; replacing with new");
6210 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006211 } else {
6212 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6213 // If what we are scanning is a system package, then
6214 // make it so, regardless of whether it was previously
6215 // installed only in the data partition.
6216 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 }
6219 }
6220 if (p == null) {
6221 // Create a new PackageSettings entry. this can end up here because
6222 // of code path mismatch or user id mismatch of an updated system partition
6223 if (!create) {
6224 return null;
6225 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006226 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006228 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006229 if (sharedUser != null) {
6230 p.userId = sharedUser.userId;
6231 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006232 // Clone the setting here for disabled system packages
6233 PackageSetting dis = mDisabledSysPackages.get(name);
6234 if (dis != null) {
6235 // For disabled packages a new setting is created
6236 // from the existing user id. This still has to be
6237 // added to list of user id's
6238 // Copy signatures from previous setting
6239 if (dis.signatures.mSignatures != null) {
6240 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6241 }
6242 p.userId = dis.userId;
6243 // Clone permissions
6244 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6245 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6246 // Clone component info
6247 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6248 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6249 // Add new setting to list of user ids
6250 addUserIdLP(p.userId, p, name);
6251 } else {
6252 // Assign new user id
6253 p.userId = newUserIdLP(p);
6254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 } else {
6256 p.userId = FIRST_APPLICATION_UID;
6257 }
6258 if (p.userId < 0) {
6259 reportSettingsProblem(Log.WARN,
6260 "Package " + name + " could not be assigned a valid uid");
6261 return null;
6262 }
6263 if (add) {
6264 // Finish adding new package by adding it and updating shared
6265 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006266 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 }
6268 }
6269 return p;
6270 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006271
6272 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6273 File codePath, File resourcePath) {
6274 p.pkg = pkg;
6275 // Update code path if needed
6276 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6277 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006278 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006279 p.codePath = codePath;
6280 p.codePathString = codePath.toString();
6281 }
6282 //Update resource path if needed
6283 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6284 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006285 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006286 p.resourcePath = resourcePath;
6287 p.resourcePathString = resourcePath.toString();
6288 }
6289 // Update version code if needed
6290 if (pkg.mVersionCode != p.versionCode) {
6291 p.versionCode = pkg.mVersionCode;
6292 }
6293 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6294 }
6295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 // Utility method that adds a PackageSetting to mPackages and
6297 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006298 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299 SharedUserSetting sharedUser) {
6300 mPackages.put(name, p);
6301 if (sharedUser != null) {
6302 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6303 reportSettingsProblem(Log.ERROR,
6304 "Package " + p.name + " was user "
6305 + p.sharedUser + " but is now " + sharedUser
6306 + "; I am not changing its files so it will probably fail!");
6307 p.sharedUser.packages.remove(p);
6308 } else if (p.userId != sharedUser.userId) {
6309 reportSettingsProblem(Log.ERROR,
6310 "Package " + p.name + " was user id " + p.userId
6311 + " but is now user " + sharedUser
6312 + " with id " + sharedUser.userId
6313 + "; I am not changing its files so it will probably fail!");
6314 }
6315
6316 sharedUser.packages.add(p);
6317 p.sharedUser = sharedUser;
6318 p.userId = sharedUser.userId;
6319 }
6320 }
6321
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006322 /*
6323 * Update the shared user setting when a package using
6324 * specifying the shared user id is removed. The gids
6325 * associated with each permission of the deleted package
6326 * are removed from the shared user's gid list only if its
6327 * not in use by other permissions of packages in the
6328 * shared user setting.
6329 */
6330 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6332 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6333 return;
6334 }
6335 // No sharedUserId
6336 if (deletedPs.sharedUser == null) {
6337 return;
6338 }
6339 SharedUserSetting sus = deletedPs.sharedUser;
6340 // Update permissions
6341 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6342 boolean used = false;
6343 if (!sus.grantedPermissions.contains (eachPerm)) {
6344 continue;
6345 }
6346 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006347 if (pkg.pkg != null &&
6348 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6349 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006350 used = true;
6351 break;
6352 }
6353 }
6354 if (!used) {
6355 // can safely delete this permission from list
6356 sus.grantedPermissions.remove(eachPerm);
6357 sus.loadedPermissions.remove(eachPerm);
6358 }
6359 }
6360 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006361 int newGids[] = globalGids;
6362 for (String eachPerm : sus.grantedPermissions) {
6363 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006364 if (bp != null) {
6365 newGids = appendInts(newGids, bp.gids);
6366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 }
6368 sus.gids = newGids;
6369 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 private int removePackageLP(String name) {
6372 PackageSetting p = mPackages.get(name);
6373 if (p != null) {
6374 mPackages.remove(name);
6375 if (p.sharedUser != null) {
6376 p.sharedUser.packages.remove(p);
6377 if (p.sharedUser.packages.size() == 0) {
6378 mSharedUsers.remove(p.sharedUser.name);
6379 removeUserIdLP(p.sharedUser.userId);
6380 return p.sharedUser.userId;
6381 }
6382 } else {
6383 removeUserIdLP(p.userId);
6384 return p.userId;
6385 }
6386 }
6387 return -1;
6388 }
6389
6390 private boolean addUserIdLP(int uid, Object obj, Object name) {
6391 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6392 return false;
6393 }
6394
6395 if (uid >= FIRST_APPLICATION_UID) {
6396 int N = mUserIds.size();
6397 final int index = uid - FIRST_APPLICATION_UID;
6398 while (index >= N) {
6399 mUserIds.add(null);
6400 N++;
6401 }
6402 if (mUserIds.get(index) != null) {
6403 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006404 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 + " name=" + name);
6406 return false;
6407 }
6408 mUserIds.set(index, obj);
6409 } else {
6410 if (mOtherUserIds.get(uid) != null) {
6411 reportSettingsProblem(Log.ERROR,
6412 "Adding duplicate shared id: " + uid
6413 + " name=" + name);
6414 return false;
6415 }
6416 mOtherUserIds.put(uid, obj);
6417 }
6418 return true;
6419 }
6420
6421 public Object getUserIdLP(int uid) {
6422 if (uid >= FIRST_APPLICATION_UID) {
6423 int N = mUserIds.size();
6424 final int index = uid - FIRST_APPLICATION_UID;
6425 return index < N ? mUserIds.get(index) : null;
6426 } else {
6427 return mOtherUserIds.get(uid);
6428 }
6429 }
6430
6431 private void removeUserIdLP(int uid) {
6432 if (uid >= FIRST_APPLICATION_UID) {
6433 int N = mUserIds.size();
6434 final int index = uid - FIRST_APPLICATION_UID;
6435 if (index < N) mUserIds.set(index, null);
6436 } else {
6437 mOtherUserIds.remove(uid);
6438 }
6439 }
6440
6441 void writeLP() {
6442 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6443
6444 // Keep the old settings around until we know the new ones have
6445 // been successfully written.
6446 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006447 // Presence of backup settings file indicates that we failed
6448 // to persist settings earlier. So preserve the older
6449 // backup for future reference since the current settings
6450 // might have been corrupted.
6451 if (!mBackupSettingsFilename.exists()) {
6452 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6453 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6454 return;
6455 }
6456 } else {
6457 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 }
6460
6461 mPastSignatures.clear();
6462
6463 try {
6464 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6465
6466 //XmlSerializer serializer = XmlUtils.serializerInstance();
6467 XmlSerializer serializer = new FastXmlSerializer();
6468 serializer.setOutput(str, "utf-8");
6469 serializer.startDocument(null, true);
6470 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6471
6472 serializer.startTag(null, "packages");
6473
6474 serializer.startTag(null, "permission-trees");
6475 for (BasePermission bp : mPermissionTrees.values()) {
6476 writePermission(serializer, bp);
6477 }
6478 serializer.endTag(null, "permission-trees");
6479
6480 serializer.startTag(null, "permissions");
6481 for (BasePermission bp : mPermissions.values()) {
6482 writePermission(serializer, bp);
6483 }
6484 serializer.endTag(null, "permissions");
6485
6486 for (PackageSetting pkg : mPackages.values()) {
6487 writePackage(serializer, pkg);
6488 }
6489
6490 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6491 writeDisabledSysPackage(serializer, pkg);
6492 }
6493
6494 serializer.startTag(null, "preferred-packages");
6495 int N = mPreferredPackages.size();
6496 for (int i=0; i<N; i++) {
6497 PackageSetting pkg = mPreferredPackages.get(i);
6498 serializer.startTag(null, "item");
6499 serializer.attribute(null, "name", pkg.name);
6500 serializer.endTag(null, "item");
6501 }
6502 serializer.endTag(null, "preferred-packages");
6503
6504 serializer.startTag(null, "preferred-activities");
6505 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6506 serializer.startTag(null, "item");
6507 pa.writeToXml(serializer);
6508 serializer.endTag(null, "item");
6509 }
6510 serializer.endTag(null, "preferred-activities");
6511
6512 for (SharedUserSetting usr : mSharedUsers.values()) {
6513 serializer.startTag(null, "shared-user");
6514 serializer.attribute(null, "name", usr.name);
6515 serializer.attribute(null, "userId",
6516 Integer.toString(usr.userId));
6517 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6518 serializer.startTag(null, "perms");
6519 for (String name : usr.grantedPermissions) {
6520 serializer.startTag(null, "item");
6521 serializer.attribute(null, "name", name);
6522 serializer.endTag(null, "item");
6523 }
6524 serializer.endTag(null, "perms");
6525 serializer.endTag(null, "shared-user");
6526 }
6527
6528 serializer.endTag(null, "packages");
6529
6530 serializer.endDocument();
6531
6532 str.flush();
6533 str.close();
6534
6535 // New settings successfully written, old ones are no longer
6536 // needed.
6537 mBackupSettingsFilename.delete();
6538 FileUtils.setPermissions(mSettingsFilename.toString(),
6539 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6540 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6541 |FileUtils.S_IROTH,
6542 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006543 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544
6545 } catch(XmlPullParserException e) {
6546 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 -08006547 } catch(java.io.IOException e) {
6548 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 -08006549 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006550 // Clean up partially written file
6551 if (mSettingsFilename.exists()) {
6552 if (!mSettingsFilename.delete()) {
6553 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6554 }
6555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006556 //Debug.stopMethodTracing();
6557 }
6558
6559 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
6560 throws java.io.IOException {
6561 serializer.startTag(null, "updated-package");
6562 serializer.attribute(null, "name", pkg.name);
6563 serializer.attribute(null, "codePath", pkg.codePathString);
6564 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006565 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6567 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6568 }
6569 if (pkg.sharedUser == null) {
6570 serializer.attribute(null, "userId",
6571 Integer.toString(pkg.userId));
6572 } else {
6573 serializer.attribute(null, "sharedUserId",
6574 Integer.toString(pkg.userId));
6575 }
6576 serializer.startTag(null, "perms");
6577 if (pkg.sharedUser == null) {
6578 // If this is a shared user, the permissions will
6579 // be written there. We still need to write an
6580 // empty permissions list so permissionsFixed will
6581 // be set.
6582 for (final String name : pkg.grantedPermissions) {
6583 BasePermission bp = mPermissions.get(name);
6584 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6585 // We only need to write signature or system permissions but this wont
6586 // match the semantics of grantedPermissions. So write all permissions.
6587 serializer.startTag(null, "item");
6588 serializer.attribute(null, "name", name);
6589 serializer.endTag(null, "item");
6590 }
6591 }
6592 }
6593 serializer.endTag(null, "perms");
6594 serializer.endTag(null, "updated-package");
6595 }
6596
6597 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6598 throws java.io.IOException {
6599 serializer.startTag(null, "package");
6600 serializer.attribute(null, "name", pkg.name);
6601 serializer.attribute(null, "codePath", pkg.codePathString);
6602 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6603 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6604 }
6605 serializer.attribute(null, "system",
6606 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6607 ? "true" : "false");
6608 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006609 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006610 if (pkg.sharedUser == null) {
6611 serializer.attribute(null, "userId",
6612 Integer.toString(pkg.userId));
6613 } else {
6614 serializer.attribute(null, "sharedUserId",
6615 Integer.toString(pkg.userId));
6616 }
6617 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6618 serializer.attribute(null, "enabled",
6619 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6620 ? "true" : "false");
6621 }
6622 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6623 serializer.attribute(null, "installStatus", "false");
6624 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006625 if (pkg.installerPackageName != null) {
6626 serializer.attribute(null, "installer", pkg.installerPackageName);
6627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6629 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6630 serializer.startTag(null, "perms");
6631 if (pkg.sharedUser == null) {
6632 // If this is a shared user, the permissions will
6633 // be written there. We still need to write an
6634 // empty permissions list so permissionsFixed will
6635 // be set.
6636 for (final String name : pkg.grantedPermissions) {
6637 serializer.startTag(null, "item");
6638 serializer.attribute(null, "name", name);
6639 serializer.endTag(null, "item");
6640 }
6641 }
6642 serializer.endTag(null, "perms");
6643 }
6644 if (pkg.disabledComponents.size() > 0) {
6645 serializer.startTag(null, "disabled-components");
6646 for (final String name : pkg.disabledComponents) {
6647 serializer.startTag(null, "item");
6648 serializer.attribute(null, "name", name);
6649 serializer.endTag(null, "item");
6650 }
6651 serializer.endTag(null, "disabled-components");
6652 }
6653 if (pkg.enabledComponents.size() > 0) {
6654 serializer.startTag(null, "enabled-components");
6655 for (final String name : pkg.enabledComponents) {
6656 serializer.startTag(null, "item");
6657 serializer.attribute(null, "name", name);
6658 serializer.endTag(null, "item");
6659 }
6660 serializer.endTag(null, "enabled-components");
6661 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 serializer.endTag(null, "package");
6664 }
6665
6666 void writePermission(XmlSerializer serializer, BasePermission bp)
6667 throws XmlPullParserException, java.io.IOException {
6668 if (bp.type != BasePermission.TYPE_BUILTIN
6669 && bp.sourcePackage != null) {
6670 serializer.startTag(null, "item");
6671 serializer.attribute(null, "name", bp.name);
6672 serializer.attribute(null, "package", bp.sourcePackage);
6673 if (DEBUG_SETTINGS) Log.v(TAG,
6674 "Writing perm: name=" + bp.name + " type=" + bp.type);
6675 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6676 PermissionInfo pi = bp.perm != null ? bp.perm.info
6677 : bp.pendingInfo;
6678 if (pi != null) {
6679 serializer.attribute(null, "type", "dynamic");
6680 if (pi.icon != 0) {
6681 serializer.attribute(null, "icon",
6682 Integer.toString(pi.icon));
6683 }
6684 if (pi.nonLocalizedLabel != null) {
6685 serializer.attribute(null, "label",
6686 pi.nonLocalizedLabel.toString());
6687 }
6688 if (pi.protectionLevel !=
6689 PermissionInfo.PROTECTION_NORMAL) {
6690 serializer.attribute(null, "protection",
6691 Integer.toString(pi.protectionLevel));
6692 }
6693 }
6694 }
6695 serializer.endTag(null, "item");
6696 }
6697 }
6698
6699 String getReadMessagesLP() {
6700 return mReadMessages.toString();
6701 }
6702
6703 ArrayList<String> getListOfIncompleteInstallPackages() {
6704 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6705 Iterator<String> its = kList.iterator();
6706 ArrayList<String> ret = new ArrayList<String>();
6707 while(its.hasNext()) {
6708 String key = its.next();
6709 PackageSetting ps = mPackages.get(key);
6710 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6711 ret.add(key);
6712 }
6713 }
6714 return ret;
6715 }
6716
6717 boolean readLP() {
6718 FileInputStream str = null;
6719 if (mBackupSettingsFilename.exists()) {
6720 try {
6721 str = new FileInputStream(mBackupSettingsFilename);
6722 mReadMessages.append("Reading from backup settings file\n");
6723 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006724 if (mSettingsFilename.exists()) {
6725 // If both the backup and settings file exist, we
6726 // ignore the settings since it might have been
6727 // corrupted.
6728 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6729 mSettingsFilename.delete();
6730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 } catch (java.io.IOException e) {
6732 // We'll try for the normal settings file.
6733 }
6734 }
6735
6736 mPastSignatures.clear();
6737
6738 try {
6739 if (str == null) {
6740 if (!mSettingsFilename.exists()) {
6741 mReadMessages.append("No settings file found\n");
6742 Log.i(TAG, "No current settings file!");
6743 return false;
6744 }
6745 str = new FileInputStream(mSettingsFilename);
6746 }
6747 XmlPullParser parser = Xml.newPullParser();
6748 parser.setInput(str, null);
6749
6750 int type;
6751 while ((type=parser.next()) != XmlPullParser.START_TAG
6752 && type != XmlPullParser.END_DOCUMENT) {
6753 ;
6754 }
6755
6756 if (type != XmlPullParser.START_TAG) {
6757 mReadMessages.append("No start tag found in settings file\n");
6758 Log.e(TAG, "No start tag found in package manager settings");
6759 return false;
6760 }
6761
6762 int outerDepth = parser.getDepth();
6763 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6764 && (type != XmlPullParser.END_TAG
6765 || parser.getDepth() > outerDepth)) {
6766 if (type == XmlPullParser.END_TAG
6767 || type == XmlPullParser.TEXT) {
6768 continue;
6769 }
6770
6771 String tagName = parser.getName();
6772 if (tagName.equals("package")) {
6773 readPackageLP(parser);
6774 } else if (tagName.equals("permissions")) {
6775 readPermissionsLP(mPermissions, parser);
6776 } else if (tagName.equals("permission-trees")) {
6777 readPermissionsLP(mPermissionTrees, parser);
6778 } else if (tagName.equals("shared-user")) {
6779 readSharedUserLP(parser);
6780 } else if (tagName.equals("preferred-packages")) {
6781 readPreferredPackagesLP(parser);
6782 } else if (tagName.equals("preferred-activities")) {
6783 readPreferredActivitiesLP(parser);
6784 } else if(tagName.equals("updated-package")) {
6785 readDisabledSysPackageLP(parser);
6786 } else {
6787 Log.w(TAG, "Unknown element under <packages>: "
6788 + parser.getName());
6789 XmlUtils.skipCurrentTag(parser);
6790 }
6791 }
6792
6793 str.close();
6794
6795 } catch(XmlPullParserException e) {
6796 mReadMessages.append("Error reading: " + e.toString());
6797 Log.e(TAG, "Error reading package manager settings", e);
6798
6799 } catch(java.io.IOException e) {
6800 mReadMessages.append("Error reading: " + e.toString());
6801 Log.e(TAG, "Error reading package manager settings", e);
6802
6803 }
6804
6805 int N = mPendingPackages.size();
6806 for (int i=0; i<N; i++) {
6807 final PendingPackage pp = mPendingPackages.get(i);
6808 Object idObj = getUserIdLP(pp.sharedId);
6809 if (idObj != null && idObj instanceof SharedUserSetting) {
6810 PackageSetting p = getPackageLP(pp.name,
6811 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006812 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006813 if (p == null) {
6814 Log.w(TAG, "Unable to create application package for "
6815 + pp.name);
6816 continue;
6817 }
6818 p.copyFrom(pp);
6819 } else if (idObj != null) {
6820 String msg = "Bad package setting: package " + pp.name
6821 + " has shared uid " + pp.sharedId
6822 + " that is not a shared uid\n";
6823 mReadMessages.append(msg);
6824 Log.e(TAG, msg);
6825 } else {
6826 String msg = "Bad package setting: package " + pp.name
6827 + " has shared uid " + pp.sharedId
6828 + " that is not defined\n";
6829 mReadMessages.append(msg);
6830 Log.e(TAG, msg);
6831 }
6832 }
6833 mPendingPackages.clear();
6834
6835 N = mPendingPreferredPackages.size();
6836 mPreferredPackages.clear();
6837 for (int i=0; i<N; i++) {
6838 final String name = mPendingPreferredPackages.get(i);
6839 final PackageSetting p = mPackages.get(name);
6840 if (p != null) {
6841 mPreferredPackages.add(p);
6842 } else {
6843 Log.w(TAG, "Unknown preferred package: " + name);
6844 }
6845 }
6846 mPendingPreferredPackages.clear();
6847
6848 mReadMessages.append("Read completed successfully: "
6849 + mPackages.size() + " packages, "
6850 + mSharedUsers.size() + " shared uids\n");
6851
6852 return true;
6853 }
6854
6855 private int readInt(XmlPullParser parser, String ns, String name,
6856 int defValue) {
6857 String v = parser.getAttributeValue(ns, name);
6858 try {
6859 if (v == null) {
6860 return defValue;
6861 }
6862 return Integer.parseInt(v);
6863 } catch (NumberFormatException e) {
6864 reportSettingsProblem(Log.WARN,
6865 "Error in package manager settings: attribute " +
6866 name + " has bad integer value " + v + " at "
6867 + parser.getPositionDescription());
6868 }
6869 return defValue;
6870 }
6871
6872 private void readPermissionsLP(HashMap<String, BasePermission> out,
6873 XmlPullParser parser)
6874 throws IOException, XmlPullParserException {
6875 int outerDepth = parser.getDepth();
6876 int type;
6877 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6878 && (type != XmlPullParser.END_TAG
6879 || parser.getDepth() > outerDepth)) {
6880 if (type == XmlPullParser.END_TAG
6881 || type == XmlPullParser.TEXT) {
6882 continue;
6883 }
6884
6885 String tagName = parser.getName();
6886 if (tagName.equals("item")) {
6887 String name = parser.getAttributeValue(null, "name");
6888 String sourcePackage = parser.getAttributeValue(null, "package");
6889 String ptype = parser.getAttributeValue(null, "type");
6890 if (name != null && sourcePackage != null) {
6891 boolean dynamic = "dynamic".equals(ptype);
6892 BasePermission bp = new BasePermission(name, sourcePackage,
6893 dynamic
6894 ? BasePermission.TYPE_DYNAMIC
6895 : BasePermission.TYPE_NORMAL);
6896 if (dynamic) {
6897 PermissionInfo pi = new PermissionInfo();
6898 pi.packageName = sourcePackage.intern();
6899 pi.name = name.intern();
6900 pi.icon = readInt(parser, null, "icon", 0);
6901 pi.nonLocalizedLabel = parser.getAttributeValue(
6902 null, "label");
6903 pi.protectionLevel = readInt(parser, null, "protection",
6904 PermissionInfo.PROTECTION_NORMAL);
6905 bp.pendingInfo = pi;
6906 }
6907 out.put(bp.name, bp);
6908 } else {
6909 reportSettingsProblem(Log.WARN,
6910 "Error in package manager settings: permissions has"
6911 + " no name at " + parser.getPositionDescription());
6912 }
6913 } else {
6914 reportSettingsProblem(Log.WARN,
6915 "Unknown element reading permissions: "
6916 + parser.getName() + " at "
6917 + parser.getPositionDescription());
6918 }
6919 XmlUtils.skipCurrentTag(parser);
6920 }
6921 }
6922
6923 private void readDisabledSysPackageLP(XmlPullParser parser)
6924 throws XmlPullParserException, IOException {
6925 String name = parser.getAttributeValue(null, "name");
6926 String codePathStr = parser.getAttributeValue(null, "codePath");
6927 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6928 if(resourcePathStr == null) {
6929 resourcePathStr = codePathStr;
6930 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006931 String version = parser.getAttributeValue(null, "version");
6932 int versionCode = 0;
6933 if (version != null) {
6934 try {
6935 versionCode = Integer.parseInt(version);
6936 } catch (NumberFormatException e) {
6937 }
6938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006939
6940 int pkgFlags = 0;
6941 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6942 PackageSetting ps = new PackageSetting(name,
6943 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006944 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 String timeStampStr = parser.getAttributeValue(null, "ts");
6946 if (timeStampStr != null) {
6947 try {
6948 long timeStamp = Long.parseLong(timeStampStr);
6949 ps.setTimeStamp(timeStamp, timeStampStr);
6950 } catch (NumberFormatException e) {
6951 }
6952 }
6953 String idStr = parser.getAttributeValue(null, "userId");
6954 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6955 if(ps.userId <= 0) {
6956 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6957 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6958 }
6959 int outerDepth = parser.getDepth();
6960 int type;
6961 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6962 && (type != XmlPullParser.END_TAG
6963 || parser.getDepth() > outerDepth)) {
6964 if (type == XmlPullParser.END_TAG
6965 || type == XmlPullParser.TEXT) {
6966 continue;
6967 }
6968
6969 String tagName = parser.getName();
6970 if (tagName.equals("perms")) {
6971 readGrantedPermissionsLP(parser,
6972 ps.grantedPermissions);
6973 } else {
6974 reportSettingsProblem(Log.WARN,
6975 "Unknown element under <updated-package>: "
6976 + parser.getName());
6977 XmlUtils.skipCurrentTag(parser);
6978 }
6979 }
6980 mDisabledSysPackages.put(name, ps);
6981 }
6982
6983 private void readPackageLP(XmlPullParser parser)
6984 throws XmlPullParserException, IOException {
6985 String name = null;
6986 String idStr = null;
6987 String sharedIdStr = null;
6988 String codePathStr = null;
6989 String resourcePathStr = null;
6990 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02006991 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006992 int pkgFlags = 0;
6993 String timeStampStr;
6994 long timeStamp = 0;
6995 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006996 String version = null;
6997 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 try {
6999 name = parser.getAttributeValue(null, "name");
7000 idStr = parser.getAttributeValue(null, "userId");
7001 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7002 codePathStr = parser.getAttributeValue(null, "codePath");
7003 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007004 version = parser.getAttributeValue(null, "version");
7005 if (version != null) {
7006 try {
7007 versionCode = Integer.parseInt(version);
7008 } catch (NumberFormatException e) {
7009 }
7010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007012 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 if (systemStr != null) {
7014 if ("true".equals(systemStr)) {
7015 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7016 }
7017 } else {
7018 // Old settings that don't specify system... just treat
7019 // them as system, good enough.
7020 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7021 }
7022 timeStampStr = parser.getAttributeValue(null, "ts");
7023 if (timeStampStr != null) {
7024 try {
7025 timeStamp = Long.parseLong(timeStampStr);
7026 } catch (NumberFormatException e) {
7027 }
7028 }
7029 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7030 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7031 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7032 if (resourcePathStr == null) {
7033 resourcePathStr = codePathStr;
7034 }
7035 if (name == null) {
7036 reportSettingsProblem(Log.WARN,
7037 "Error in package manager settings: <package> has no name at "
7038 + parser.getPositionDescription());
7039 } else if (codePathStr == null) {
7040 reportSettingsProblem(Log.WARN,
7041 "Error in package manager settings: <package> has no codePath at "
7042 + parser.getPositionDescription());
7043 } else if (userId > 0) {
7044 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007045 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7047 + ": userId=" + userId + " pkg=" + packageSetting);
7048 if (packageSetting == null) {
7049 reportSettingsProblem(Log.ERROR,
7050 "Failure adding uid " + userId
7051 + " while parsing settings at "
7052 + parser.getPositionDescription());
7053 } else {
7054 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7055 }
7056 } else if (sharedIdStr != null) {
7057 userId = sharedIdStr != null
7058 ? Integer.parseInt(sharedIdStr) : 0;
7059 if (userId > 0) {
7060 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007061 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7063 mPendingPackages.add((PendingPackage) packageSetting);
7064 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7065 + ": sharedUserId=" + userId + " pkg="
7066 + packageSetting);
7067 } else {
7068 reportSettingsProblem(Log.WARN,
7069 "Error in package manager settings: package "
7070 + name + " has bad sharedId " + sharedIdStr
7071 + " at " + parser.getPositionDescription());
7072 }
7073 } else {
7074 reportSettingsProblem(Log.WARN,
7075 "Error in package manager settings: package "
7076 + name + " has bad userId " + idStr + " at "
7077 + parser.getPositionDescription());
7078 }
7079 } catch (NumberFormatException e) {
7080 reportSettingsProblem(Log.WARN,
7081 "Error in package manager settings: package "
7082 + name + " has bad userId " + idStr + " at "
7083 + parser.getPositionDescription());
7084 }
7085 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007086 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087 final String enabledStr = parser.getAttributeValue(null, "enabled");
7088 if (enabledStr != null) {
7089 if (enabledStr.equalsIgnoreCase("true")) {
7090 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7091 } else if (enabledStr.equalsIgnoreCase("false")) {
7092 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7093 } else if (enabledStr.equalsIgnoreCase("default")) {
7094 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7095 } else {
7096 reportSettingsProblem(Log.WARN,
7097 "Error in package manager settings: package "
7098 + name + " has bad enabled value: " + idStr
7099 + " at " + parser.getPositionDescription());
7100 }
7101 } else {
7102 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7103 }
7104 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7105 if (installStatusStr != null) {
7106 if (installStatusStr.equalsIgnoreCase("false")) {
7107 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7108 } else {
7109 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7110 }
7111 }
7112
7113 int outerDepth = parser.getDepth();
7114 int type;
7115 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7116 && (type != XmlPullParser.END_TAG
7117 || parser.getDepth() > outerDepth)) {
7118 if (type == XmlPullParser.END_TAG
7119 || type == XmlPullParser.TEXT) {
7120 continue;
7121 }
7122
7123 String tagName = parser.getName();
7124 if (tagName.equals("disabled-components")) {
7125 readDisabledComponentsLP(packageSetting, parser);
7126 } else if (tagName.equals("enabled-components")) {
7127 readEnabledComponentsLP(packageSetting, parser);
7128 } else if (tagName.equals("sigs")) {
7129 packageSetting.signatures.readXml(parser, mPastSignatures);
7130 } else if (tagName.equals("perms")) {
7131 readGrantedPermissionsLP(parser,
7132 packageSetting.loadedPermissions);
7133 packageSetting.permissionsFixed = true;
7134 } else {
7135 reportSettingsProblem(Log.WARN,
7136 "Unknown element under <package>: "
7137 + parser.getName());
7138 XmlUtils.skipCurrentTag(parser);
7139 }
7140 }
7141 } else {
7142 XmlUtils.skipCurrentTag(parser);
7143 }
7144 }
7145
7146 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7147 XmlPullParser parser)
7148 throws IOException, XmlPullParserException {
7149 int outerDepth = parser.getDepth();
7150 int type;
7151 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7152 && (type != XmlPullParser.END_TAG
7153 || parser.getDepth() > outerDepth)) {
7154 if (type == XmlPullParser.END_TAG
7155 || type == XmlPullParser.TEXT) {
7156 continue;
7157 }
7158
7159 String tagName = parser.getName();
7160 if (tagName.equals("item")) {
7161 String name = parser.getAttributeValue(null, "name");
7162 if (name != null) {
7163 packageSetting.disabledComponents.add(name.intern());
7164 } else {
7165 reportSettingsProblem(Log.WARN,
7166 "Error in package manager settings: <disabled-components> has"
7167 + " no name at " + parser.getPositionDescription());
7168 }
7169 } else {
7170 reportSettingsProblem(Log.WARN,
7171 "Unknown element under <disabled-components>: "
7172 + parser.getName());
7173 }
7174 XmlUtils.skipCurrentTag(parser);
7175 }
7176 }
7177
7178 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7179 XmlPullParser parser)
7180 throws IOException, XmlPullParserException {
7181 int outerDepth = parser.getDepth();
7182 int type;
7183 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7184 && (type != XmlPullParser.END_TAG
7185 || parser.getDepth() > outerDepth)) {
7186 if (type == XmlPullParser.END_TAG
7187 || type == XmlPullParser.TEXT) {
7188 continue;
7189 }
7190
7191 String tagName = parser.getName();
7192 if (tagName.equals("item")) {
7193 String name = parser.getAttributeValue(null, "name");
7194 if (name != null) {
7195 packageSetting.enabledComponents.add(name.intern());
7196 } else {
7197 reportSettingsProblem(Log.WARN,
7198 "Error in package manager settings: <enabled-components> has"
7199 + " no name at " + parser.getPositionDescription());
7200 }
7201 } else {
7202 reportSettingsProblem(Log.WARN,
7203 "Unknown element under <enabled-components>: "
7204 + parser.getName());
7205 }
7206 XmlUtils.skipCurrentTag(parser);
7207 }
7208 }
7209
7210 private void readSharedUserLP(XmlPullParser parser)
7211 throws XmlPullParserException, IOException {
7212 String name = null;
7213 String idStr = null;
7214 int pkgFlags = 0;
7215 SharedUserSetting su = null;
7216 try {
7217 name = parser.getAttributeValue(null, "name");
7218 idStr = parser.getAttributeValue(null, "userId");
7219 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7220 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7221 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7222 }
7223 if (name == null) {
7224 reportSettingsProblem(Log.WARN,
7225 "Error in package manager settings: <shared-user> has no name at "
7226 + parser.getPositionDescription());
7227 } else if (userId == 0) {
7228 reportSettingsProblem(Log.WARN,
7229 "Error in package manager settings: shared-user "
7230 + name + " has bad userId " + idStr + " at "
7231 + parser.getPositionDescription());
7232 } else {
7233 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7234 reportSettingsProblem(Log.ERROR,
7235 "Occurred while parsing settings at "
7236 + parser.getPositionDescription());
7237 }
7238 }
7239 } catch (NumberFormatException e) {
7240 reportSettingsProblem(Log.WARN,
7241 "Error in package manager settings: package "
7242 + name + " has bad userId " + idStr + " at "
7243 + parser.getPositionDescription());
7244 };
7245
7246 if (su != null) {
7247 int outerDepth = parser.getDepth();
7248 int type;
7249 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7250 && (type != XmlPullParser.END_TAG
7251 || parser.getDepth() > outerDepth)) {
7252 if (type == XmlPullParser.END_TAG
7253 || type == XmlPullParser.TEXT) {
7254 continue;
7255 }
7256
7257 String tagName = parser.getName();
7258 if (tagName.equals("sigs")) {
7259 su.signatures.readXml(parser, mPastSignatures);
7260 } else if (tagName.equals("perms")) {
7261 readGrantedPermissionsLP(parser, su.loadedPermissions);
7262 } else {
7263 reportSettingsProblem(Log.WARN,
7264 "Unknown element under <shared-user>: "
7265 + parser.getName());
7266 XmlUtils.skipCurrentTag(parser);
7267 }
7268 }
7269
7270 } else {
7271 XmlUtils.skipCurrentTag(parser);
7272 }
7273 }
7274
7275 private void readGrantedPermissionsLP(XmlPullParser parser,
7276 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7277 int outerDepth = parser.getDepth();
7278 int type;
7279 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7280 && (type != XmlPullParser.END_TAG
7281 || parser.getDepth() > outerDepth)) {
7282 if (type == XmlPullParser.END_TAG
7283 || type == XmlPullParser.TEXT) {
7284 continue;
7285 }
7286
7287 String tagName = parser.getName();
7288 if (tagName.equals("item")) {
7289 String name = parser.getAttributeValue(null, "name");
7290 if (name != null) {
7291 outPerms.add(name.intern());
7292 } else {
7293 reportSettingsProblem(Log.WARN,
7294 "Error in package manager settings: <perms> has"
7295 + " no name at " + parser.getPositionDescription());
7296 }
7297 } else {
7298 reportSettingsProblem(Log.WARN,
7299 "Unknown element under <perms>: "
7300 + parser.getName());
7301 }
7302 XmlUtils.skipCurrentTag(parser);
7303 }
7304 }
7305
7306 private void readPreferredPackagesLP(XmlPullParser parser)
7307 throws XmlPullParserException, IOException {
7308 int outerDepth = parser.getDepth();
7309 int type;
7310 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7311 && (type != XmlPullParser.END_TAG
7312 || parser.getDepth() > outerDepth)) {
7313 if (type == XmlPullParser.END_TAG
7314 || type == XmlPullParser.TEXT) {
7315 continue;
7316 }
7317
7318 String tagName = parser.getName();
7319 if (tagName.equals("item")) {
7320 String name = parser.getAttributeValue(null, "name");
7321 if (name != null) {
7322 mPendingPreferredPackages.add(name);
7323 } else {
7324 reportSettingsProblem(Log.WARN,
7325 "Error in package manager settings: <preferred-package> has no name at "
7326 + parser.getPositionDescription());
7327 }
7328 } else {
7329 reportSettingsProblem(Log.WARN,
7330 "Unknown element under <preferred-packages>: "
7331 + parser.getName());
7332 }
7333 XmlUtils.skipCurrentTag(parser);
7334 }
7335 }
7336
7337 private void readPreferredActivitiesLP(XmlPullParser parser)
7338 throws XmlPullParserException, IOException {
7339 int outerDepth = parser.getDepth();
7340 int type;
7341 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7342 && (type != XmlPullParser.END_TAG
7343 || parser.getDepth() > outerDepth)) {
7344 if (type == XmlPullParser.END_TAG
7345 || type == XmlPullParser.TEXT) {
7346 continue;
7347 }
7348
7349 String tagName = parser.getName();
7350 if (tagName.equals("item")) {
7351 PreferredActivity pa = new PreferredActivity(parser);
7352 if (pa.mParseError == null) {
7353 mPreferredActivities.addFilter(pa);
7354 } else {
7355 reportSettingsProblem(Log.WARN,
7356 "Error in package manager settings: <preferred-activity> "
7357 + pa.mParseError + " at "
7358 + parser.getPositionDescription());
7359 }
7360 } else {
7361 reportSettingsProblem(Log.WARN,
7362 "Unknown element under <preferred-activities>: "
7363 + parser.getName());
7364 XmlUtils.skipCurrentTag(parser);
7365 }
7366 }
7367 }
7368
7369 // Returns -1 if we could not find an available UserId to assign
7370 private int newUserIdLP(Object obj) {
7371 // Let's be stupidly inefficient for now...
7372 final int N = mUserIds.size();
7373 for (int i=0; i<N; i++) {
7374 if (mUserIds.get(i) == null) {
7375 mUserIds.set(i, obj);
7376 return FIRST_APPLICATION_UID + i;
7377 }
7378 }
7379
7380 // None left?
7381 if (N >= MAX_APPLICATION_UIDS) {
7382 return -1;
7383 }
7384
7385 mUserIds.add(obj);
7386 return FIRST_APPLICATION_UID + N;
7387 }
7388
7389 public PackageSetting getDisabledSystemPkg(String name) {
7390 synchronized(mPackages) {
7391 PackageSetting ps = mDisabledSysPackages.get(name);
7392 return ps;
7393 }
7394 }
7395
7396 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7397 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7398 if (Config.LOGV) {
7399 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7400 + " componentName = " + componentInfo.name);
7401 Log.v(TAG, "enabledComponents: "
7402 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7403 Log.v(TAG, "disabledComponents: "
7404 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7405 }
7406 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7407 || ((componentInfo.enabled
7408 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7409 || (componentInfo.applicationInfo.enabled
7410 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7411 && !packageSettings.disabledComponents.contains(componentInfo.name))
7412 || packageSettings.enabledComponents.contains(componentInfo.name));
7413 }
7414 }
7415}