blob: 39129d4852b9fdcc76b1158ba79495b07fd5f6bc [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.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800280 final HashMap<String, ArrayList<String>> mPendingBroadcasts
281 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700282 static final int SEND_PENDING_BROADCAST = 1;
283 // Delay time in millisecs
284 static final int BROADCAST_DELAY = 10 * 1000;
285
286 class PackageHandler extends Handler {
287 PackageHandler(Looper looper) {
288 super(looper);
289 }
290 public void handleMessage(Message msg) {
291 switch (msg.what) {
292 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800293 String packages[];
294 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700295 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700296 int uids[];
297 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800298 if (mPendingBroadcasts == null) {
299 return;
300 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700301 size = mPendingBroadcasts.size();
302 if (size <= 0) {
303 // Nothing to be done. Just return
304 return;
305 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800306 packages = new String[size];
307 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700308 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800309 Iterator<HashMap.Entry<String, ArrayList<String>>>
310 it = mPendingBroadcasts.entrySet().iterator();
311 int i = 0;
312 while (it.hasNext() && i < size) {
313 HashMap.Entry<String, ArrayList<String>> ent = it.next();
314 packages[i] = ent.getKey();
315 components[i] = ent.getValue();
316 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700317 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800318 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700319 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800320 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700321 mPendingBroadcasts.clear();
322 }
323 // Send broadcasts
324 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800325 sendPackageChangedBroadcast(packages[i], true,
326 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700327 }
328 break;
329 }
330 }
331 }
332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 public static final IPackageManager main(Context context, boolean factoryTest) {
334 PackageManagerService m = new PackageManagerService(context, factoryTest);
335 ServiceManager.addService("package", m);
336 return m;
337 }
338
339 static String[] splitString(String str, char sep) {
340 int count = 1;
341 int i = 0;
342 while ((i=str.indexOf(sep, i)) >= 0) {
343 count++;
344 i++;
345 }
346
347 String[] res = new String[count];
348 i=0;
349 count = 0;
350 int lastI=0;
351 while ((i=str.indexOf(sep, i)) >= 0) {
352 res[count] = str.substring(lastI, i);
353 count++;
354 i++;
355 lastI = i;
356 }
357 res[count] = str.substring(lastI, str.length());
358 return res;
359 }
360
361 public PackageManagerService(Context context, boolean factoryTest) {
362 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
363 SystemClock.uptimeMillis());
364
365 if (mSdkVersion <= 0) {
366 Log.w(TAG, "**** ro.build.version.sdk not set!");
367 }
368
369 mContext = context;
370 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700371 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 mMetrics = new DisplayMetrics();
373 mSettings = new Settings();
374 mSettings.addSharedUserLP("android.uid.system",
375 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
376 mSettings.addSharedUserLP("android.uid.phone",
377 MULTIPLE_APPLICATION_UIDS
378 ? RADIO_UID : FIRST_APPLICATION_UID,
379 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400380 mSettings.addSharedUserLP("android.uid.log",
381 MULTIPLE_APPLICATION_UIDS
382 ? LOG_UID : FIRST_APPLICATION_UID,
383 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
385 String separateProcesses = SystemProperties.get("debug.separate_processes");
386 if (separateProcesses != null && separateProcesses.length() > 0) {
387 if ("*".equals(separateProcesses)) {
388 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
389 mSeparateProcesses = null;
390 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
391 } else {
392 mDefParseFlags = 0;
393 mSeparateProcesses = separateProcesses.split(",");
394 Log.w(TAG, "Running with debug.separate_processes: "
395 + separateProcesses);
396 }
397 } else {
398 mDefParseFlags = 0;
399 mSeparateProcesses = null;
400 }
401
402 Installer installer = new Installer();
403 // Little hacky thing to check if installd is here, to determine
404 // whether we are running on the simulator and thus need to take
405 // care of building the /data file structure ourself.
406 // (apparently the sim now has a working installer)
407 if (installer.ping() && Process.supportsProcesses()) {
408 mInstaller = installer;
409 } else {
410 mInstaller = null;
411 }
412
413 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
414 Display d = wm.getDefaultDisplay();
415 d.getMetrics(mMetrics);
416
417 synchronized (mInstallLock) {
418 synchronized (mPackages) {
419 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700420 mHandler = new PackageHandler(mHandlerThread.getLooper());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421
422 File dataDir = Environment.getDataDirectory();
423 mAppDataDir = new File(dataDir, "data");
424 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
425
426 if (mInstaller == null) {
427 // Make sure these dirs exist, when we are running in
428 // the simulator.
429 // Make a wide-open directory for random misc stuff.
430 File miscDir = new File(dataDir, "misc");
431 miscDir.mkdirs();
432 mAppDataDir.mkdirs();
433 mDrmAppPrivateInstallDir.mkdirs();
434 }
435
436 readPermissions();
437
438 mRestoredSettings = mSettings.readLP();
439 long startTime = SystemClock.uptimeMillis();
440
441 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
442 startTime);
443
444 int scanMode = SCAN_MONITOR;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700445 if (mNoDexOpt) {
446 Log.w(TAG, "Running ENG build: no pre-dexopt!");
447 scanMode |= SCAN_NO_DEX;
448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449
450 final HashSet<String> libFiles = new HashSet<String>();
451
452 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700453 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454
455 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700456 boolean didDexOpt = false;
457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 /**
459 * Out of paranoia, ensure that everything in the boot class
460 * path has been dexed.
461 */
462 String bootClassPath = System.getProperty("java.boot.class.path");
463 if (bootClassPath != null) {
464 String[] paths = splitString(bootClassPath, ':');
465 for (int i=0; i<paths.length; i++) {
466 try {
467 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
468 libFiles.add(paths[i]);
469 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700470 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 }
472 } catch (FileNotFoundException e) {
473 Log.w(TAG, "Boot class path not found: " + paths[i]);
474 } catch (IOException e) {
475 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
476 }
477 }
478 } else {
479 Log.w(TAG, "No BOOTCLASSPATH found!");
480 }
481
482 /**
483 * Also ensure all external libraries have had dexopt run on them.
484 */
485 if (mSharedLibraries.size() > 0) {
486 Iterator<String> libs = mSharedLibraries.values().iterator();
487 while (libs.hasNext()) {
488 String lib = libs.next();
489 try {
490 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
491 libFiles.add(lib);
492 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700493 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 }
495 } catch (FileNotFoundException e) {
496 Log.w(TAG, "Library not found: " + lib);
497 } catch (IOException e) {
498 Log.w(TAG, "Exception reading library: " + lib, e);
499 }
500 }
501 }
502
503 // Gross hack for now: we know this file doesn't contain any
504 // code, so don't dexopt it to avoid the resulting log spew.
505 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
506
507 /**
508 * And there are a number of commands implemented in Java, which
509 * we currently need to do the dexopt on so that they can be
510 * run from a non-root shell.
511 */
512 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700513 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 for (int i=0; i<frameworkFiles.length; i++) {
515 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
516 String path = libPath.getPath();
517 // Skip the file if we alrady did it.
518 if (libFiles.contains(path)) {
519 continue;
520 }
521 // Skip the file if it is not a type we want to dexopt.
522 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
523 continue;
524 }
525 try {
526 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
527 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700528 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 }
530 } catch (FileNotFoundException e) {
531 Log.w(TAG, "Jar not found: " + path);
532 } catch (IOException e) {
533 Log.w(TAG, "Exception reading jar: " + path, e);
534 }
535 }
536 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700537
538 if (didDexOpt) {
539 // If we had to do a dexopt of one of the previous
540 // things, then something on the system has changed.
541 // Consider this significant, and wipe away all other
542 // existing dexopt files to ensure we don't leave any
543 // dangling around.
544 String[] files = mDalvikCacheDir.list();
545 if (files != null) {
546 for (int i=0; i<files.length; i++) {
547 String fn = files[i];
548 if (fn.startsWith("data@app@")
549 || fn.startsWith("data@app-private@")) {
550 Log.i(TAG, "Pruning dalvik file: " + fn);
551 (new File(mDalvikCacheDir, fn)).delete();
552 }
553 }
554 }
555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 }
557
558 mFrameworkInstallObserver = new AppDirObserver(
559 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
560 mFrameworkInstallObserver.startWatching();
561 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
562 scanMode | SCAN_NO_DEX);
563 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
564 mSystemInstallObserver = new AppDirObserver(
565 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
566 mSystemInstallObserver.startWatching();
567 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
568 mAppInstallDir = new File(dataDir, "app");
569 if (mInstaller == null) {
570 // Make sure these dirs exist, when we are running in
571 // the simulator.
572 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
573 }
574 //look for any incomplete package installations
575 ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
576 //clean up list
577 for(int i = 0; i < deletePkgsList.size(); i++) {
578 //clean up here
579 cleanupInstallFailedPackage(deletePkgsList.get(i));
580 }
581 //delete tmp files
582 deleteTempPackageFiles();
583
584 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
585 SystemClock.uptimeMillis());
586 mAppInstallObserver = new AppDirObserver(
587 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
588 mAppInstallObserver.startWatching();
589 scanDirLI(mAppInstallDir, 0, scanMode);
590
591 mDrmAppInstallObserver = new AppDirObserver(
592 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
593 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -0700594 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595
596 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
597 SystemClock.uptimeMillis());
598 Log.i(TAG, "Time to scan packages: "
599 + ((SystemClock.uptimeMillis()-startTime)/1000f)
600 + " seconds");
601
602 updatePermissionsLP();
603
604 mSettings.writeLP();
605
606 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
607 SystemClock.uptimeMillis());
608
609 // Now after opening every single application zip, make sure they
610 // are all flushed. Not really needed, but keeps things nice and
611 // tidy.
612 Runtime.getRuntime().gc();
613 } // synchronized (mPackages)
614 } // synchronized (mInstallLock)
615 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 @Override
618 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
619 throws RemoteException {
620 try {
621 return super.onTransact(code, data, reply, flags);
622 } catch (RuntimeException e) {
623 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
624 Log.e(TAG, "Package Manager Crash", e);
625 }
626 throw e;
627 }
628 }
629
630 void cleanupInstallFailedPackage(String packageName) {
631 if (mInstaller != null) {
632 int retCode = mInstaller.remove(packageName);
633 if (retCode < 0) {
634 Log.w(TAG, "Couldn't remove app data directory for package: "
635 + packageName + ", retcode=" + retCode);
636 }
637 } else {
638 //for emulator
639 PackageParser.Package pkg = mPackages.get(packageName);
640 File dataDir = new File(pkg.applicationInfo.dataDir);
641 dataDir.delete();
642 }
643 mSettings.removePackageLP(packageName);
644 }
645
646 void readPermissions() {
647 // Read permissions from .../etc/permission directory.
648 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
649 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
650 Log.w(TAG, "No directory " + libraryDir + ", skipping");
651 return;
652 }
653 if (!libraryDir.canRead()) {
654 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
655 return;
656 }
657
658 // Iterate over the files in the directory and scan .xml files
659 for (File f : libraryDir.listFiles()) {
660 // We'll read platform.xml last
661 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
662 continue;
663 }
664
665 if (!f.getPath().endsWith(".xml")) {
666 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
667 continue;
668 }
669 if (!f.canRead()) {
670 Log.w(TAG, "Permissions library file " + f + " cannot be read");
671 continue;
672 }
673
674 readPermissionsFromXml(f);
675 }
676
677 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
678 final File permFile = new File(Environment.getRootDirectory(),
679 "etc/permissions/platform.xml");
680 readPermissionsFromXml(permFile);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700681
682 StringBuilder sb = new StringBuilder(128);
683 sb.append("Libs:");
684 Iterator<String> it = mSharedLibraries.keySet().iterator();
685 while (it.hasNext()) {
686 sb.append(' ');
687 String name = it.next();
688 sb.append(name);
689 sb.append(':');
690 sb.append(mSharedLibraries.get(name));
691 }
692 Log.i(TAG, sb.toString());
693
694 sb.setLength(0);
695 sb.append("Features:");
696 it = mAvailableFeatures.keySet().iterator();
697 while (it.hasNext()) {
698 sb.append(' ');
699 sb.append(it.next());
700 }
701 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 }
703
704 private void readPermissionsFromXml(File permFile) {
705 FileReader permReader = null;
706 try {
707 permReader = new FileReader(permFile);
708 } catch (FileNotFoundException e) {
709 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
710 return;
711 }
712
713 try {
714 XmlPullParser parser = Xml.newPullParser();
715 parser.setInput(permReader);
716
717 XmlUtils.beginDocument(parser, "permissions");
718
719 while (true) {
720 XmlUtils.nextElement(parser);
721 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
722 break;
723 }
724
725 String name = parser.getName();
726 if ("group".equals(name)) {
727 String gidStr = parser.getAttributeValue(null, "gid");
728 if (gidStr != null) {
729 int gid = Integer.parseInt(gidStr);
730 mGlobalGids = appendInt(mGlobalGids, gid);
731 } else {
732 Log.w(TAG, "<group> without gid at "
733 + parser.getPositionDescription());
734 }
735
736 XmlUtils.skipCurrentTag(parser);
737 continue;
738 } else if ("permission".equals(name)) {
739 String perm = parser.getAttributeValue(null, "name");
740 if (perm == null) {
741 Log.w(TAG, "<permission> without name at "
742 + parser.getPositionDescription());
743 XmlUtils.skipCurrentTag(parser);
744 continue;
745 }
746 perm = perm.intern();
747 readPermission(parser, perm);
748
749 } else if ("assign-permission".equals(name)) {
750 String perm = parser.getAttributeValue(null, "name");
751 if (perm == null) {
752 Log.w(TAG, "<assign-permission> without name at "
753 + parser.getPositionDescription());
754 XmlUtils.skipCurrentTag(parser);
755 continue;
756 }
757 String uidStr = parser.getAttributeValue(null, "uid");
758 if (uidStr == null) {
759 Log.w(TAG, "<assign-permission> without uid at "
760 + parser.getPositionDescription());
761 XmlUtils.skipCurrentTag(parser);
762 continue;
763 }
764 int uid = Process.getUidForName(uidStr);
765 if (uid < 0) {
766 Log.w(TAG, "<assign-permission> with unknown uid \""
767 + uidStr + "\" at "
768 + parser.getPositionDescription());
769 XmlUtils.skipCurrentTag(parser);
770 continue;
771 }
772 perm = perm.intern();
773 HashSet<String> perms = mSystemPermissions.get(uid);
774 if (perms == null) {
775 perms = new HashSet<String>();
776 mSystemPermissions.put(uid, perms);
777 }
778 perms.add(perm);
779 XmlUtils.skipCurrentTag(parser);
780
781 } else if ("library".equals(name)) {
782 String lname = parser.getAttributeValue(null, "name");
783 String lfile = parser.getAttributeValue(null, "file");
784 if (lname == null) {
785 Log.w(TAG, "<library> without name at "
786 + parser.getPositionDescription());
787 } else if (lfile == null) {
788 Log.w(TAG, "<library> without file at "
789 + parser.getPositionDescription());
790 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700791 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700792 mSharedLibraries.put(lname, lfile);
793 }
794 XmlUtils.skipCurrentTag(parser);
795 continue;
796
797 } else if ("feature".equals(name)) {
798 String fname = parser.getAttributeValue(null, "name");
799 if (fname == null) {
800 Log.w(TAG, "<feature> without name at "
801 + parser.getPositionDescription());
802 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700803 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700804 FeatureInfo fi = new FeatureInfo();
805 fi.name = fname;
806 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
808 XmlUtils.skipCurrentTag(parser);
809 continue;
810
811 } else {
812 XmlUtils.skipCurrentTag(parser);
813 continue;
814 }
815
816 }
817 } catch (XmlPullParserException e) {
818 Log.w(TAG, "Got execption parsing permissions.", e);
819 } catch (IOException e) {
820 Log.w(TAG, "Got execption parsing permissions.", e);
821 }
822 }
823
824 void readPermission(XmlPullParser parser, String name)
825 throws IOException, XmlPullParserException {
826
827 name = name.intern();
828
829 BasePermission bp = mSettings.mPermissions.get(name);
830 if (bp == null) {
831 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
832 mSettings.mPermissions.put(name, bp);
833 }
834 int outerDepth = parser.getDepth();
835 int type;
836 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
837 && (type != XmlPullParser.END_TAG
838 || parser.getDepth() > outerDepth)) {
839 if (type == XmlPullParser.END_TAG
840 || type == XmlPullParser.TEXT) {
841 continue;
842 }
843
844 String tagName = parser.getName();
845 if ("group".equals(tagName)) {
846 String gidStr = parser.getAttributeValue(null, "gid");
847 if (gidStr != null) {
848 int gid = Process.getGidForName(gidStr);
849 bp.gids = appendInt(bp.gids, gid);
850 } else {
851 Log.w(TAG, "<group> without gid at "
852 + parser.getPositionDescription());
853 }
854 }
855 XmlUtils.skipCurrentTag(parser);
856 }
857 }
858
859 static int[] appendInt(int[] cur, int val) {
860 if (cur == null) {
861 return new int[] { val };
862 }
863 final int N = cur.length;
864 for (int i=0; i<N; i++) {
865 if (cur[i] == val) {
866 return cur;
867 }
868 }
869 int[] ret = new int[N+1];
870 System.arraycopy(cur, 0, ret, 0, N);
871 ret[N] = val;
872 return ret;
873 }
874
875 static int[] appendInts(int[] cur, int[] add) {
876 if (add == null) return cur;
877 if (cur == null) return add;
878 final int N = add.length;
879 for (int i=0; i<N; i++) {
880 cur = appendInt(cur, add[i]);
881 }
882 return cur;
883 }
884
885 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700886 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
887 // The package has been uninstalled but has retained data and resources.
888 return PackageParser.generatePackageInfo(p, null, flags);
889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 final PackageSetting ps = (PackageSetting)p.mExtras;
891 if (ps == null) {
892 return null;
893 }
894 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
895 return PackageParser.generatePackageInfo(p, gp.gids, flags);
896 }
897
898 public PackageInfo getPackageInfo(String packageName, int flags) {
899 synchronized (mPackages) {
900 PackageParser.Package p = mPackages.get(packageName);
901 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700902 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 + ": " + p);
904 if (p != null) {
905 return generatePackageInfo(p, flags);
906 }
907 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
908 return generatePackageInfoFromSettingsLP(packageName, flags);
909 }
910 }
911 return null;
912 }
913
914 public int getPackageUid(String packageName) {
915 synchronized (mPackages) {
916 PackageParser.Package p = mPackages.get(packageName);
917 if(p != null) {
918 return p.applicationInfo.uid;
919 }
920 PackageSetting ps = mSettings.mPackages.get(packageName);
921 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
922 return -1;
923 }
924 p = ps.pkg;
925 return p != null ? p.applicationInfo.uid : -1;
926 }
927 }
928
929 public int[] getPackageGids(String packageName) {
930 synchronized (mPackages) {
931 PackageParser.Package p = mPackages.get(packageName);
932 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700933 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 + ": " + p);
935 if (p != null) {
936 final PackageSetting ps = (PackageSetting)p.mExtras;
937 final SharedUserSetting suid = ps.sharedUser;
938 return suid != null ? suid.gids : ps.gids;
939 }
940 }
941 // stupid thing to indicate an error.
942 return new int[0];
943 }
944
945 public PermissionInfo getPermissionInfo(String name, int flags) {
946 synchronized (mPackages) {
947 final BasePermission p = mSettings.mPermissions.get(name);
948 if (p != null && p.perm != null) {
949 return PackageParser.generatePermissionInfo(p.perm, flags);
950 }
951 return null;
952 }
953 }
954
955 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
956 synchronized (mPackages) {
957 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
958 for (BasePermission p : mSettings.mPermissions.values()) {
959 if (group == null) {
960 if (p.perm.info.group == null) {
961 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
962 }
963 } else {
964 if (group.equals(p.perm.info.group)) {
965 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
966 }
967 }
968 }
969
970 if (out.size() > 0) {
971 return out;
972 }
973 return mPermissionGroups.containsKey(group) ? out : null;
974 }
975 }
976
977 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
978 synchronized (mPackages) {
979 return PackageParser.generatePermissionGroupInfo(
980 mPermissionGroups.get(name), flags);
981 }
982 }
983
984 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
985 synchronized (mPackages) {
986 final int N = mPermissionGroups.size();
987 ArrayList<PermissionGroupInfo> out
988 = new ArrayList<PermissionGroupInfo>(N);
989 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
990 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
991 }
992 return out;
993 }
994 }
995
996 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
997 PackageSetting ps = mSettings.mPackages.get(packageName);
998 if(ps != null) {
999 if(ps.pkg == null) {
1000 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1001 if(pInfo != null) {
1002 return pInfo.applicationInfo;
1003 }
1004 return null;
1005 }
1006 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1007 }
1008 return null;
1009 }
1010
1011 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1012 PackageSetting ps = mSettings.mPackages.get(packageName);
1013 if(ps != null) {
1014 if(ps.pkg == null) {
1015 ps.pkg = new PackageParser.Package(packageName);
1016 ps.pkg.applicationInfo.packageName = packageName;
1017 }
1018 return generatePackageInfo(ps.pkg, flags);
1019 }
1020 return null;
1021 }
1022
1023 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1024 synchronized (mPackages) {
1025 PackageParser.Package p = mPackages.get(packageName);
1026 if (Config.LOGV) Log.v(
1027 TAG, "getApplicationInfo " + packageName
1028 + ": " + p);
1029 if (p != null) {
1030 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001031 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 }
1033 if ("android".equals(packageName)||"system".equals(packageName)) {
1034 return mAndroidApplication;
1035 }
1036 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1037 return generateApplicationInfoFromSettingsLP(packageName, flags);
1038 }
1039 }
1040 return null;
1041 }
1042
1043
1044 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1045 mContext.enforceCallingOrSelfPermission(
1046 android.Manifest.permission.CLEAR_APP_CACHE, null);
1047 // Queue up an async operation since clearing cache may take a little while.
1048 mHandler.post(new Runnable() {
1049 public void run() {
1050 mHandler.removeCallbacks(this);
1051 int retCode = -1;
1052 if (mInstaller != null) {
1053 retCode = mInstaller.freeCache(freeStorageSize);
1054 if (retCode < 0) {
1055 Log.w(TAG, "Couldn't clear application caches");
1056 }
1057 } //end if mInstaller
1058 if (observer != null) {
1059 try {
1060 observer.onRemoveCompleted(null, (retCode >= 0));
1061 } catch (RemoteException e) {
1062 Log.w(TAG, "RemoveException when invoking call back");
1063 }
1064 }
1065 }
1066 });
1067 }
1068
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001069 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001070 mContext.enforceCallingOrSelfPermission(
1071 android.Manifest.permission.CLEAR_APP_CACHE, null);
1072 // Queue up an async operation since clearing cache may take a little while.
1073 mHandler.post(new Runnable() {
1074 public void run() {
1075 mHandler.removeCallbacks(this);
1076 int retCode = -1;
1077 if (mInstaller != null) {
1078 retCode = mInstaller.freeCache(freeStorageSize);
1079 if (retCode < 0) {
1080 Log.w(TAG, "Couldn't clear application caches");
1081 }
1082 }
1083 if(pi != null) {
1084 try {
1085 // Callback via pending intent
1086 int code = (retCode >= 0) ? 1 : 0;
1087 pi.sendIntent(null, code, null,
1088 null, null);
1089 } catch (SendIntentException e1) {
1090 Log.i(TAG, "Failed to send pending intent");
1091 }
1092 }
1093 }
1094 });
1095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096
1097 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1098 synchronized (mPackages) {
1099 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001100
1101 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001103 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 }
1105 if (mResolveComponentName.equals(component)) {
1106 return mResolveActivity;
1107 }
1108 }
1109 return null;
1110 }
1111
1112 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1113 synchronized (mPackages) {
1114 PackageParser.Activity a = mReceivers.mActivities.get(component);
1115 if (Config.LOGV) Log.v(
1116 TAG, "getReceiverInfo " + component + ": " + a);
1117 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1118 return PackageParser.generateActivityInfo(a, flags);
1119 }
1120 }
1121 return null;
1122 }
1123
1124 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1125 synchronized (mPackages) {
1126 PackageParser.Service s = mServices.mServices.get(component);
1127 if (Config.LOGV) Log.v(
1128 TAG, "getServiceInfo " + component + ": " + s);
1129 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1130 return PackageParser.generateServiceInfo(s, flags);
1131 }
1132 }
1133 return null;
1134 }
1135
1136 public String[] getSystemSharedLibraryNames() {
1137 Set<String> libSet;
1138 synchronized (mPackages) {
1139 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001140 int size = libSet.size();
1141 if (size > 0) {
1142 String[] libs = new String[size];
1143 libSet.toArray(libs);
1144 return libs;
1145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001147 return null;
1148 }
1149
1150 public FeatureInfo[] getSystemAvailableFeatures() {
1151 Collection<FeatureInfo> featSet;
1152 synchronized (mPackages) {
1153 featSet = mAvailableFeatures.values();
1154 int size = featSet.size();
1155 if (size > 0) {
1156 FeatureInfo[] features = new FeatureInfo[size+1];
1157 featSet.toArray(features);
1158 FeatureInfo fi = new FeatureInfo();
1159 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1160 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1161 features[size] = fi;
1162 return features;
1163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 }
1165 return null;
1166 }
1167
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001168 public boolean hasSystemFeature(String name) {
1169 synchronized (mPackages) {
1170 return mAvailableFeatures.containsKey(name);
1171 }
1172 }
1173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 public int checkPermission(String permName, String pkgName) {
1175 synchronized (mPackages) {
1176 PackageParser.Package p = mPackages.get(pkgName);
1177 if (p != null && p.mExtras != null) {
1178 PackageSetting ps = (PackageSetting)p.mExtras;
1179 if (ps.sharedUser != null) {
1180 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1181 return PackageManager.PERMISSION_GRANTED;
1182 }
1183 } else if (ps.grantedPermissions.contains(permName)) {
1184 return PackageManager.PERMISSION_GRANTED;
1185 }
1186 }
1187 }
1188 return PackageManager.PERMISSION_DENIED;
1189 }
1190
1191 public int checkUidPermission(String permName, int uid) {
1192 synchronized (mPackages) {
1193 Object obj = mSettings.getUserIdLP(uid);
1194 if (obj != null) {
1195 if (obj instanceof SharedUserSetting) {
1196 SharedUserSetting sus = (SharedUserSetting)obj;
1197 if (sus.grantedPermissions.contains(permName)) {
1198 return PackageManager.PERMISSION_GRANTED;
1199 }
1200 } else if (obj instanceof PackageSetting) {
1201 PackageSetting ps = (PackageSetting)obj;
1202 if (ps.grantedPermissions.contains(permName)) {
1203 return PackageManager.PERMISSION_GRANTED;
1204 }
1205 }
1206 } else {
1207 HashSet<String> perms = mSystemPermissions.get(uid);
1208 if (perms != null && perms.contains(permName)) {
1209 return PackageManager.PERMISSION_GRANTED;
1210 }
1211 }
1212 }
1213 return PackageManager.PERMISSION_DENIED;
1214 }
1215
1216 private BasePermission findPermissionTreeLP(String permName) {
1217 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1218 if (permName.startsWith(bp.name) &&
1219 permName.length() > bp.name.length() &&
1220 permName.charAt(bp.name.length()) == '.') {
1221 return bp;
1222 }
1223 }
1224 return null;
1225 }
1226
1227 private BasePermission checkPermissionTreeLP(String permName) {
1228 if (permName != null) {
1229 BasePermission bp = findPermissionTreeLP(permName);
1230 if (bp != null) {
1231 if (bp.uid == Binder.getCallingUid()) {
1232 return bp;
1233 }
1234 throw new SecurityException("Calling uid "
1235 + Binder.getCallingUid()
1236 + " is not allowed to add to permission tree "
1237 + bp.name + " owned by uid " + bp.uid);
1238 }
1239 }
1240 throw new SecurityException("No permission tree found for " + permName);
1241 }
1242
1243 public boolean addPermission(PermissionInfo info) {
1244 synchronized (mPackages) {
1245 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1246 throw new SecurityException("Label must be specified in permission");
1247 }
1248 BasePermission tree = checkPermissionTreeLP(info.name);
1249 BasePermission bp = mSettings.mPermissions.get(info.name);
1250 boolean added = bp == null;
1251 if (added) {
1252 bp = new BasePermission(info.name, tree.sourcePackage,
1253 BasePermission.TYPE_DYNAMIC);
1254 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1255 throw new SecurityException(
1256 "Not allowed to modify non-dynamic permission "
1257 + info.name);
1258 }
1259 bp.perm = new PackageParser.Permission(tree.perm.owner,
1260 new PermissionInfo(info));
1261 bp.perm.info.packageName = tree.perm.info.packageName;
1262 bp.uid = tree.uid;
1263 if (added) {
1264 mSettings.mPermissions.put(info.name, bp);
1265 }
1266 mSettings.writeLP();
1267 return added;
1268 }
1269 }
1270
1271 public void removePermission(String name) {
1272 synchronized (mPackages) {
1273 checkPermissionTreeLP(name);
1274 BasePermission bp = mSettings.mPermissions.get(name);
1275 if (bp != null) {
1276 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1277 throw new SecurityException(
1278 "Not allowed to modify non-dynamic permission "
1279 + name);
1280 }
1281 mSettings.mPermissions.remove(name);
1282 mSettings.writeLP();
1283 }
1284 }
1285 }
1286
Dianne Hackborn854060af2009-07-09 18:14:31 -07001287 public boolean isProtectedBroadcast(String actionName) {
1288 synchronized (mPackages) {
1289 return mProtectedBroadcasts.contains(actionName);
1290 }
1291 }
1292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 public int checkSignatures(String pkg1, String pkg2) {
1294 synchronized (mPackages) {
1295 PackageParser.Package p1 = mPackages.get(pkg1);
1296 PackageParser.Package p2 = mPackages.get(pkg2);
1297 if (p1 == null || p1.mExtras == null
1298 || p2 == null || p2.mExtras == null) {
1299 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1300 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001301 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 }
1303 }
1304
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001305 public int checkUidSignatures(int uid1, int uid2) {
1306 synchronized (mPackages) {
1307 Signature[] s1;
1308 Signature[] s2;
1309 Object obj = mSettings.getUserIdLP(uid1);
1310 if (obj != null) {
1311 if (obj instanceof SharedUserSetting) {
1312 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1313 } else if (obj instanceof PackageSetting) {
1314 s1 = ((PackageSetting)obj).signatures.mSignatures;
1315 } else {
1316 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1317 }
1318 } else {
1319 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1320 }
1321 obj = mSettings.getUserIdLP(uid2);
1322 if (obj != null) {
1323 if (obj instanceof SharedUserSetting) {
1324 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1325 } else if (obj instanceof PackageSetting) {
1326 s2 = ((PackageSetting)obj).signatures.mSignatures;
1327 } else {
1328 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1329 }
1330 } else {
1331 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1332 }
1333 return checkSignaturesLP(s1, s2);
1334 }
1335 }
1336
1337 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1338 if (s1 == null) {
1339 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1341 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1342 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001343 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1345 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001346 final int N1 = s1.length;
1347 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 for (int i=0; i<N1; i++) {
1349 boolean match = false;
1350 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001351 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 match = true;
1353 break;
1354 }
1355 }
1356 if (!match) {
1357 return PackageManager.SIGNATURE_NO_MATCH;
1358 }
1359 }
1360 return PackageManager.SIGNATURE_MATCH;
1361 }
1362
1363 public String[] getPackagesForUid(int uid) {
1364 synchronized (mPackages) {
1365 Object obj = mSettings.getUserIdLP(uid);
1366 if (obj instanceof SharedUserSetting) {
1367 SharedUserSetting sus = (SharedUserSetting)obj;
1368 final int N = sus.packages.size();
1369 String[] res = new String[N];
1370 Iterator<PackageSetting> it = sus.packages.iterator();
1371 int i=0;
1372 while (it.hasNext()) {
1373 res[i++] = it.next().name;
1374 }
1375 return res;
1376 } else if (obj instanceof PackageSetting) {
1377 PackageSetting ps = (PackageSetting)obj;
1378 return new String[] { ps.name };
1379 }
1380 }
1381 return null;
1382 }
1383
1384 public String getNameForUid(int uid) {
1385 synchronized (mPackages) {
1386 Object obj = mSettings.getUserIdLP(uid);
1387 if (obj instanceof SharedUserSetting) {
1388 SharedUserSetting sus = (SharedUserSetting)obj;
1389 return sus.name + ":" + sus.userId;
1390 } else if (obj instanceof PackageSetting) {
1391 PackageSetting ps = (PackageSetting)obj;
1392 return ps.name;
1393 }
1394 }
1395 return null;
1396 }
1397
1398 public int getUidForSharedUser(String sharedUserName) {
1399 if(sharedUserName == null) {
1400 return -1;
1401 }
1402 synchronized (mPackages) {
1403 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1404 if(suid == null) {
1405 return -1;
1406 }
1407 return suid.userId;
1408 }
1409 }
1410
1411 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1412 int flags) {
1413 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001414 return chooseBestActivity(intent, resolvedType, flags, query);
1415 }
1416
Mihai Predaeae850c2009-05-13 10:13:48 +02001417 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1418 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 if (query != null) {
1420 final int N = query.size();
1421 if (N == 1) {
1422 return query.get(0);
1423 } else if (N > 1) {
1424 // If there is more than one activity with the same priority,
1425 // then let the user decide between them.
1426 ResolveInfo r0 = query.get(0);
1427 ResolveInfo r1 = query.get(1);
1428 if (false) {
1429 System.out.println(r0.activityInfo.name +
1430 "=" + r0.priority + " vs " +
1431 r1.activityInfo.name +
1432 "=" + r1.priority);
1433 }
1434 // If the first activity has a higher priority, or a different
1435 // default, then it is always desireable to pick it.
1436 if (r0.priority != r1.priority
1437 || r0.preferredOrder != r1.preferredOrder
1438 || r0.isDefault != r1.isDefault) {
1439 return query.get(0);
1440 }
1441 // If we have saved a preference for a preferred activity for
1442 // this Intent, use that.
1443 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1444 flags, query, r0.priority);
1445 if (ri != null) {
1446 return ri;
1447 }
1448 return mResolveInfo;
1449 }
1450 }
1451 return null;
1452 }
1453
1454 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1455 int flags, List<ResolveInfo> query, int priority) {
1456 synchronized (mPackages) {
1457 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1458 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001459 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1461 if (prefs != null && prefs.size() > 0) {
1462 // First figure out how good the original match set is.
1463 // We will only allow preferred activities that came
1464 // from the same match quality.
1465 int match = 0;
1466 final int N = query.size();
1467 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1468 for (int j=0; j<N; j++) {
1469 ResolveInfo ri = query.get(j);
1470 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1471 + ": 0x" + Integer.toHexString(match));
1472 if (ri.match > match) match = ri.match;
1473 }
1474 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1475 + Integer.toHexString(match));
1476 match &= IntentFilter.MATCH_CATEGORY_MASK;
1477 final int M = prefs.size();
1478 for (int i=0; i<M; i++) {
1479 PreferredActivity pa = prefs.get(i);
1480 if (pa.mMatch != match) {
1481 continue;
1482 }
1483 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1484 if (DEBUG_PREFERRED) {
1485 Log.v(TAG, "Got preferred activity:");
1486 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1487 }
1488 if (ai != null) {
1489 for (int j=0; j<N; j++) {
1490 ResolveInfo ri = query.get(j);
1491 if (!ri.activityInfo.applicationInfo.packageName
1492 .equals(ai.applicationInfo.packageName)) {
1493 continue;
1494 }
1495 if (!ri.activityInfo.name.equals(ai.name)) {
1496 continue;
1497 }
1498
1499 // Okay we found a previously set preferred app.
1500 // If the result set is different from when this
1501 // was created, we need to clear it and re-ask the
1502 // user their preference.
1503 if (!pa.sameSet(query, priority)) {
1504 Log.i(TAG, "Result set changed, dropping preferred activity for "
1505 + intent + " type " + resolvedType);
1506 mSettings.mPreferredActivities.removeFilter(pa);
1507 return null;
1508 }
1509
1510 // Yay!
1511 return ri;
1512 }
1513 }
1514 }
1515 }
1516 }
1517 return null;
1518 }
1519
1520 public List<ResolveInfo> queryIntentActivities(Intent intent,
1521 String resolvedType, int flags) {
1522 ComponentName comp = intent.getComponent();
1523 if (comp != null) {
1524 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1525 ActivityInfo ai = getActivityInfo(comp, flags);
1526 if (ai != null) {
1527 ResolveInfo ri = new ResolveInfo();
1528 ri.activityInfo = ai;
1529 list.add(ri);
1530 }
1531 return list;
1532 }
1533
1534 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001535 String pkgName = intent.getPackage();
1536 if (pkgName == null) {
1537 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1538 resolvedType, flags);
1539 }
1540 PackageParser.Package pkg = mPackages.get(pkgName);
1541 if (pkg != null) {
1542 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1543 resolvedType, flags, pkg.activities);
1544 }
1545 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 }
1547 }
1548
1549 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1550 Intent[] specifics, String[] specificTypes, Intent intent,
1551 String resolvedType, int flags) {
1552 final String resultsAction = intent.getAction();
1553
1554 List<ResolveInfo> results = queryIntentActivities(
1555 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1556 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1557
1558 int specificsPos = 0;
1559 int N;
1560
1561 // todo: note that the algorithm used here is O(N^2). This
1562 // isn't a problem in our current environment, but if we start running
1563 // into situations where we have more than 5 or 10 matches then this
1564 // should probably be changed to something smarter...
1565
1566 // First we go through and resolve each of the specific items
1567 // that were supplied, taking care of removing any corresponding
1568 // duplicate items in the generic resolve list.
1569 if (specifics != null) {
1570 for (int i=0; i<specifics.length; i++) {
1571 final Intent sintent = specifics[i];
1572 if (sintent == null) {
1573 continue;
1574 }
1575
1576 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1577 String action = sintent.getAction();
1578 if (resultsAction != null && resultsAction.equals(action)) {
1579 // If this action was explicitly requested, then don't
1580 // remove things that have it.
1581 action = null;
1582 }
1583 ComponentName comp = sintent.getComponent();
1584 ResolveInfo ri = null;
1585 ActivityInfo ai = null;
1586 if (comp == null) {
1587 ri = resolveIntent(
1588 sintent,
1589 specificTypes != null ? specificTypes[i] : null,
1590 flags);
1591 if (ri == null) {
1592 continue;
1593 }
1594 if (ri == mResolveInfo) {
1595 // ACK! Must do something better with this.
1596 }
1597 ai = ri.activityInfo;
1598 comp = new ComponentName(ai.applicationInfo.packageName,
1599 ai.name);
1600 } else {
1601 ai = getActivityInfo(comp, flags);
1602 if (ai == null) {
1603 continue;
1604 }
1605 }
1606
1607 // Look for any generic query activities that are duplicates
1608 // of this specific one, and remove them from the results.
1609 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1610 N = results.size();
1611 int j;
1612 for (j=specificsPos; j<N; j++) {
1613 ResolveInfo sri = results.get(j);
1614 if ((sri.activityInfo.name.equals(comp.getClassName())
1615 && sri.activityInfo.applicationInfo.packageName.equals(
1616 comp.getPackageName()))
1617 || (action != null && sri.filter.matchAction(action))) {
1618 results.remove(j);
1619 if (Config.LOGV) Log.v(
1620 TAG, "Removing duplicate item from " + j
1621 + " due to specific " + specificsPos);
1622 if (ri == null) {
1623 ri = sri;
1624 }
1625 j--;
1626 N--;
1627 }
1628 }
1629
1630 // Add this specific item to its proper place.
1631 if (ri == null) {
1632 ri = new ResolveInfo();
1633 ri.activityInfo = ai;
1634 }
1635 results.add(specificsPos, ri);
1636 ri.specificIndex = i;
1637 specificsPos++;
1638 }
1639 }
1640
1641 // Now we go through the remaining generic results and remove any
1642 // duplicate actions that are found here.
1643 N = results.size();
1644 for (int i=specificsPos; i<N-1; i++) {
1645 final ResolveInfo rii = results.get(i);
1646 if (rii.filter == null) {
1647 continue;
1648 }
1649
1650 // Iterate over all of the actions of this result's intent
1651 // filter... typically this should be just one.
1652 final Iterator<String> it = rii.filter.actionsIterator();
1653 if (it == null) {
1654 continue;
1655 }
1656 while (it.hasNext()) {
1657 final String action = it.next();
1658 if (resultsAction != null && resultsAction.equals(action)) {
1659 // If this action was explicitly requested, then don't
1660 // remove things that have it.
1661 continue;
1662 }
1663 for (int j=i+1; j<N; j++) {
1664 final ResolveInfo rij = results.get(j);
1665 if (rij.filter != null && rij.filter.hasAction(action)) {
1666 results.remove(j);
1667 if (Config.LOGV) Log.v(
1668 TAG, "Removing duplicate item from " + j
1669 + " due to action " + action + " at " + i);
1670 j--;
1671 N--;
1672 }
1673 }
1674 }
1675
1676 // If the caller didn't request filter information, drop it now
1677 // so we don't have to marshall/unmarshall it.
1678 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1679 rii.filter = null;
1680 }
1681 }
1682
1683 // Filter out the caller activity if so requested.
1684 if (caller != null) {
1685 N = results.size();
1686 for (int i=0; i<N; i++) {
1687 ActivityInfo ainfo = results.get(i).activityInfo;
1688 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1689 && caller.getClassName().equals(ainfo.name)) {
1690 results.remove(i);
1691 break;
1692 }
1693 }
1694 }
1695
1696 // If the caller didn't request filter information,
1697 // drop them now so we don't have to
1698 // marshall/unmarshall it.
1699 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1700 N = results.size();
1701 for (int i=0; i<N; i++) {
1702 results.get(i).filter = null;
1703 }
1704 }
1705
1706 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1707 return results;
1708 }
1709
1710 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1711 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001712 ComponentName comp = intent.getComponent();
1713 if (comp != null) {
1714 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1715 ActivityInfo ai = getReceiverInfo(comp, flags);
1716 if (ai != null) {
1717 ResolveInfo ri = new ResolveInfo();
1718 ri.activityInfo = ai;
1719 list.add(ri);
1720 }
1721 return list;
1722 }
1723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001725 String pkgName = intent.getPackage();
1726 if (pkgName == null) {
1727 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1728 resolvedType, flags);
1729 }
1730 PackageParser.Package pkg = mPackages.get(pkgName);
1731 if (pkg != null) {
1732 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1733 resolvedType, flags, pkg.receivers);
1734 }
1735 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 }
1737 }
1738
1739 public ResolveInfo resolveService(Intent intent, String resolvedType,
1740 int flags) {
1741 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1742 flags);
1743 if (query != null) {
1744 if (query.size() >= 1) {
1745 // If there is more than one service with the same priority,
1746 // just arbitrarily pick the first one.
1747 return query.get(0);
1748 }
1749 }
1750 return null;
1751 }
1752
1753 public List<ResolveInfo> queryIntentServices(Intent intent,
1754 String resolvedType, int flags) {
1755 ComponentName comp = intent.getComponent();
1756 if (comp != null) {
1757 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1758 ServiceInfo si = getServiceInfo(comp, flags);
1759 if (si != null) {
1760 ResolveInfo ri = new ResolveInfo();
1761 ri.serviceInfo = si;
1762 list.add(ri);
1763 }
1764 return list;
1765 }
1766
1767 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001768 String pkgName = intent.getPackage();
1769 if (pkgName == null) {
1770 return (List<ResolveInfo>)mServices.queryIntent(intent,
1771 resolvedType, flags);
1772 }
1773 PackageParser.Package pkg = mPackages.get(pkgName);
1774 if (pkg != null) {
1775 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1776 resolvedType, flags, pkg.services);
1777 }
1778 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 }
1780 }
1781
1782 public List<PackageInfo> getInstalledPackages(int flags) {
1783 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1784
1785 synchronized (mPackages) {
1786 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1787 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1788 while (i.hasNext()) {
1789 final PackageSetting ps = i.next();
1790 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1791 if(psPkg != null) {
1792 finalList.add(psPkg);
1793 }
1794 }
1795 }
1796 else {
1797 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1798 while (i.hasNext()) {
1799 final PackageParser.Package p = i.next();
1800 if (p.applicationInfo != null) {
1801 PackageInfo pi = generatePackageInfo(p, flags);
1802 if(pi != null) {
1803 finalList.add(pi);
1804 }
1805 }
1806 }
1807 }
1808 }
1809 return finalList;
1810 }
1811
1812 public List<ApplicationInfo> getInstalledApplications(int flags) {
1813 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1814 synchronized(mPackages) {
1815 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1816 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1817 while (i.hasNext()) {
1818 final PackageSetting ps = i.next();
1819 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1820 if(ai != null) {
1821 finalList.add(ai);
1822 }
1823 }
1824 }
1825 else {
1826 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1827 while (i.hasNext()) {
1828 final PackageParser.Package p = i.next();
1829 if (p.applicationInfo != null) {
1830 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1831 if(ai != null) {
1832 finalList.add(ai);
1833 }
1834 }
1835 }
1836 }
1837 }
1838 return finalList;
1839 }
1840
1841 public List<ApplicationInfo> getPersistentApplications(int flags) {
1842 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1843
1844 synchronized (mPackages) {
1845 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1846 while (i.hasNext()) {
1847 PackageParser.Package p = i.next();
1848 if (p.applicationInfo != null
1849 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1850 && (!mSafeMode || (p.applicationInfo.flags
1851 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1852 finalList.add(p.applicationInfo);
1853 }
1854 }
1855 }
1856
1857 return finalList;
1858 }
1859
1860 public ProviderInfo resolveContentProvider(String name, int flags) {
1861 synchronized (mPackages) {
1862 final PackageParser.Provider provider = mProviders.get(name);
1863 return provider != null
1864 && mSettings.isEnabledLP(provider.info, flags)
1865 && (!mSafeMode || (provider.info.applicationInfo.flags
1866 &ApplicationInfo.FLAG_SYSTEM) != 0)
1867 ? PackageParser.generateProviderInfo(provider, flags)
1868 : null;
1869 }
1870 }
1871
Fred Quintana718d8a22009-04-29 17:53:20 -07001872 /**
1873 * @deprecated
1874 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 public void querySyncProviders(List outNames, List outInfo) {
1876 synchronized (mPackages) {
1877 Iterator<Map.Entry<String, PackageParser.Provider>> i
1878 = mProviders.entrySet().iterator();
1879
1880 while (i.hasNext()) {
1881 Map.Entry<String, PackageParser.Provider> entry = i.next();
1882 PackageParser.Provider p = entry.getValue();
1883
1884 if (p.syncable
1885 && (!mSafeMode || (p.info.applicationInfo.flags
1886 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1887 outNames.add(entry.getKey());
1888 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1889 }
1890 }
1891 }
1892 }
1893
1894 public List<ProviderInfo> queryContentProviders(String processName,
1895 int uid, int flags) {
1896 ArrayList<ProviderInfo> finalList = null;
1897
1898 synchronized (mPackages) {
1899 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1900 while (i.hasNext()) {
1901 PackageParser.Provider p = i.next();
1902 if (p.info.authority != null
1903 && (processName == null ||
1904 (p.info.processName.equals(processName)
1905 && p.info.applicationInfo.uid == uid))
1906 && mSettings.isEnabledLP(p.info, flags)
1907 && (!mSafeMode || (p.info.applicationInfo.flags
1908 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1909 if (finalList == null) {
1910 finalList = new ArrayList<ProviderInfo>(3);
1911 }
1912 finalList.add(PackageParser.generateProviderInfo(p,
1913 flags));
1914 }
1915 }
1916 }
1917
1918 if (finalList != null) {
1919 Collections.sort(finalList, mProviderInitOrderSorter);
1920 }
1921
1922 return finalList;
1923 }
1924
1925 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1926 int flags) {
1927 synchronized (mPackages) {
1928 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1929 return PackageParser.generateInstrumentationInfo(i, flags);
1930 }
1931 }
1932
1933 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1934 int flags) {
1935 ArrayList<InstrumentationInfo> finalList =
1936 new ArrayList<InstrumentationInfo>();
1937
1938 synchronized (mPackages) {
1939 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1940 while (i.hasNext()) {
1941 PackageParser.Instrumentation p = i.next();
1942 if (targetPackage == null
1943 || targetPackage.equals(p.info.targetPackage)) {
1944 finalList.add(PackageParser.generateInstrumentationInfo(p,
1945 flags));
1946 }
1947 }
1948 }
1949
1950 return finalList;
1951 }
1952
1953 private void scanDirLI(File dir, int flags, int scanMode) {
1954 Log.d(TAG, "Scanning app dir " + dir);
1955
1956 String[] files = dir.list();
1957
1958 int i;
1959 for (i=0; i<files.length; i++) {
1960 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001961 File resFile = file;
1962 // Pick up the resource path from settings for fwd locked apps
1963 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1964 resFile = null;
1965 }
1966 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1968 }
1969 }
1970
1971 private static void reportSettingsProblem(int priority, String msg) {
1972 try {
1973 File dataDir = Environment.getDataDirectory();
1974 File systemDir = new File(dataDir, "system");
1975 File fname = new File(systemDir, "uiderrors.txt");
1976 FileOutputStream out = new FileOutputStream(fname, true);
1977 PrintWriter pw = new PrintWriter(out);
1978 pw.println(msg);
1979 pw.close();
1980 FileUtils.setPermissions(
1981 fname.toString(),
1982 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1983 -1, -1);
1984 } catch (java.io.IOException e) {
1985 }
1986 Log.println(priority, TAG, msg);
1987 }
1988
1989 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1990 PackageParser.Package pkg, File srcFile, int parseFlags) {
1991 if (GET_CERTIFICATES) {
1992 if (ps == null || !ps.codePath.equals(srcFile)
1993 || ps.getTimeStamp() != srcFile.lastModified()) {
1994 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1995 if (!pp.collectCertificates(pkg, parseFlags)) {
1996 mLastScanError = pp.getParseError();
1997 return false;
1998 }
1999 }
2000 }
2001 return true;
2002 }
2003
2004 /*
2005 * Scan a package and return the newly parsed package.
2006 * Returns null in case of errors and the error code is stored in mLastScanError
2007 */
2008 private PackageParser.Package scanPackageLI(File scanFile,
2009 File destCodeFile, File destResourceFile, int parseFlags,
2010 int scanMode) {
2011 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2012 parseFlags |= mDefParseFlags;
2013 PackageParser pp = new PackageParser(scanFile.getPath());
2014 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 final PackageParser.Package pkg = pp.parsePackage(scanFile,
2016 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
2017 if (pkg == null) {
2018 mLastScanError = pp.getParseError();
2019 return null;
2020 }
2021 PackageSetting ps;
2022 PackageSetting updatedPkg;
2023 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002024 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2026 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002027 // Verify certificates first
2028 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2029 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2030 return null;
2031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 if (updatedPkg != null) {
2033 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2034 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2035 }
2036 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2037 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002038 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2039 if (pkg.mVersionCode < ps.versionCode) {
2040 // The system package has been updated and the code path does not match
2041 // Ignore entry. Just return
2042 Log.w(TAG, "Package:" + pkg.packageName +
2043 " has been updated. Ignoring the one from path:"+scanFile);
2044 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2045 return null;
2046 } else {
2047 // Delete the older apk pointed to by ps
2048 // At this point, its safely assumed that package installation for
2049 // apps in system partition will go through. If not there won't be a working
2050 // version of the app
2051 synchronized (mPackages) {
2052 // Just remove the loaded entries from package lists.
2053 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002054 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002055 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2056 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 }
2059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 // The apk is forward locked (not public) if its code and resources
2061 // are kept in different files.
2062 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2063 scanMode |= SCAN_FORWARD_LOCKED;
2064 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002065 File resFile = destResourceFile;
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002066 if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002067 resFile = getFwdLockedResource(ps.name);
2068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002070 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2072 }
2073
2074 private static String fixProcessName(String defProcessName,
2075 String processName, int uid) {
2076 if (processName == null) {
2077 return defProcessName;
2078 }
2079 return processName;
2080 }
2081
2082 private boolean verifySignaturesLP(PackageSetting pkgSetting,
2083 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2084 if (pkg.mSignatures != null) {
2085 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2086 updateSignature)) {
2087 Log.e(TAG, "Package " + pkg.packageName
2088 + " signatures do not match the previously installed version; ignoring!");
2089 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2090 return false;
2091 }
2092
2093 if (pkgSetting.sharedUser != null) {
2094 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2095 pkg.mSignatures, updateSignature)) {
2096 Log.e(TAG, "Package " + pkg.packageName
2097 + " has no signatures that match those in shared user "
2098 + pkgSetting.sharedUser.name + "; ignoring!");
2099 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2100 return false;
2101 }
2102 }
2103 } else {
2104 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2105 }
2106 return true;
2107 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002108
2109 public boolean performDexOpt(String packageName) {
2110 if (!mNoDexOpt) {
2111 return false;
2112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002114 PackageParser.Package p;
2115 synchronized (mPackages) {
2116 p = mPackages.get(packageName);
2117 if (p == null || p.mDidDexOpt) {
2118 return false;
2119 }
2120 }
2121 synchronized (mInstallLock) {
2122 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2123 }
2124 }
2125
2126 static final int DEX_OPT_SKIPPED = 0;
2127 static final int DEX_OPT_PERFORMED = 1;
2128 static final int DEX_OPT_FAILED = -1;
2129
2130 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2131 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002132 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002133 String path = pkg.mScanPath;
2134 int ret = 0;
2135 try {
2136 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
2137 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
2138 !pkg.mForwardLocked);
2139 pkg.mDidDexOpt = true;
2140 performed = true;
2141 }
2142 } catch (FileNotFoundException e) {
2143 Log.w(TAG, "Apk not found for dexopt: " + path);
2144 ret = -1;
2145 } catch (IOException e) {
2146 Log.w(TAG, "Exception reading apk: " + path, e);
2147 ret = -1;
2148 }
2149 if (ret < 0) {
2150 //error from installer
2151 return DEX_OPT_FAILED;
2152 }
2153 }
2154
2155 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2156 }
2157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 private PackageParser.Package scanPackageLI(
2159 File scanFile, File destCodeFile, File destResourceFile,
2160 PackageParser.Package pkg, int parseFlags, int scanMode) {
2161
2162 mScanningPath = scanFile;
2163 if (pkg == null) {
2164 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2165 return null;
2166 }
2167
2168 final String pkgName = pkg.applicationInfo.packageName;
2169 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2170 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2171 }
2172
2173 if (pkgName.equals("android")) {
2174 synchronized (mPackages) {
2175 if (mAndroidApplication != null) {
2176 Log.w(TAG, "*************************************************");
2177 Log.w(TAG, "Core android package being redefined. Skipping.");
2178 Log.w(TAG, " file=" + mScanningPath);
2179 Log.w(TAG, "*************************************************");
2180 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2181 return null;
2182 }
2183
2184 // Set up information for our fall-back user intent resolution
2185 // activity.
2186 mPlatformPackage = pkg;
2187 pkg.mVersionCode = mSdkVersion;
2188 mAndroidApplication = pkg.applicationInfo;
2189 mResolveActivity.applicationInfo = mAndroidApplication;
2190 mResolveActivity.name = ResolverActivity.class.getName();
2191 mResolveActivity.packageName = mAndroidApplication.packageName;
2192 mResolveActivity.processName = mAndroidApplication.processName;
2193 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2194 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2195 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2196 mResolveActivity.exported = true;
2197 mResolveActivity.enabled = true;
2198 mResolveInfo.activityInfo = mResolveActivity;
2199 mResolveInfo.priority = 0;
2200 mResolveInfo.preferredOrder = 0;
2201 mResolveInfo.match = 0;
2202 mResolveComponentName = new ComponentName(
2203 mAndroidApplication.packageName, mResolveActivity.name);
2204 }
2205 }
2206
2207 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2208 TAG, "Scanning package " + pkgName);
2209 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2210 Log.w(TAG, "*************************************************");
2211 Log.w(TAG, "Application package " + pkgName
2212 + " already installed. Skipping duplicate.");
2213 Log.w(TAG, "*************************************************");
2214 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2215 return null;
2216 }
2217
2218 SharedUserSetting suid = null;
2219 PackageSetting pkgSetting = null;
2220
2221 boolean removeExisting = false;
2222
2223 synchronized (mPackages) {
2224 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002225 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2226 if (mTmpSharedLibraries == null ||
2227 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2228 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2229 }
2230 int num = 0;
2231 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2232 for (int i=0; i<N; i++) {
2233 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 if (file == null) {
2235 Log.e(TAG, "Package " + pkg.packageName
2236 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002237 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2239 return null;
2240 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002241 mTmpSharedLibraries[num] = file;
2242 num++;
2243 }
2244 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2245 for (int i=0; i<N; i++) {
2246 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2247 if (file == null) {
2248 Log.w(TAG, "Package " + pkg.packageName
2249 + " desires unavailable shared library "
2250 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2251 } else {
2252 mTmpSharedLibraries[num] = file;
2253 num++;
2254 }
2255 }
2256 if (num > 0) {
2257 pkg.usesLibraryFiles = new String[num];
2258 System.arraycopy(mTmpSharedLibraries, 0,
2259 pkg.usesLibraryFiles, 0, num);
2260 }
2261
2262 if (pkg.reqFeatures != null) {
2263 N = pkg.reqFeatures.size();
2264 for (int i=0; i<N; i++) {
2265 FeatureInfo fi = pkg.reqFeatures.get(i);
2266 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2267 // Don't care.
2268 continue;
2269 }
2270
2271 if (fi.name != null) {
2272 if (mAvailableFeatures.get(fi.name) == null) {
2273 Log.e(TAG, "Package " + pkg.packageName
2274 + " requires unavailable feature "
2275 + fi.name + "; failing!");
2276 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2277 return null;
2278 }
2279 }
2280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002281 }
2282 }
2283
2284 if (pkg.mSharedUserId != null) {
2285 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2286 pkg.applicationInfo.flags, true);
2287 if (suid == null) {
2288 Log.w(TAG, "Creating application package " + pkgName
2289 + " for shared user failed");
2290 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2291 return null;
2292 }
2293 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2294 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2295 + suid.userId + "): packages=" + suid.packages);
2296 }
2297 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002298
2299 // Just create the setting, don't add it yet. For already existing packages
2300 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2302 destResourceFile, pkg.applicationInfo.flags, true, false);
2303 if (pkgSetting == null) {
2304 Log.w(TAG, "Creating application package " + pkgName + " failed");
2305 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2306 return null;
2307 }
2308 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2309 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2310 }
2311
2312 pkg.applicationInfo.uid = pkgSetting.userId;
2313 pkg.mExtras = pkgSetting;
2314
2315 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
2316 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2317 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2318 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2319 return null;
2320 }
2321 // The signature has changed, but this package is in the system
2322 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002323 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 // However... if this package is part of a shared user, but it
2325 // doesn't match the signature of the shared user, let's fail.
2326 // What this means is that you can't change the signatures
2327 // associated with an overall shared user, which doesn't seem all
2328 // that unreasonable.
2329 if (pkgSetting.sharedUser != null) {
2330 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2331 pkg.mSignatures, false)) {
2332 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2333 return null;
2334 }
2335 }
2336 removeExisting = true;
2337 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002338
2339 // Verify that this new package doesn't have any content providers
2340 // that conflict with existing packages. Only do this if the
2341 // package isn't already installed, since we don't want to break
2342 // things that are installed.
2343 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2344 int N = pkg.providers.size();
2345 int i;
2346 for (i=0; i<N; i++) {
2347 PackageParser.Provider p = pkg.providers.get(i);
2348 String names[] = p.info.authority.split(";");
2349 for (int j = 0; j < names.length; j++) {
2350 if (mProviders.containsKey(names[j])) {
2351 PackageParser.Provider other = mProviders.get(names[j]);
2352 Log.w(TAG, "Can't install because provider name " + names[j] +
2353 " (in package " + pkg.applicationInfo.packageName +
2354 ") is already used by "
2355 + ((other != null && other.component != null)
2356 ? other.component.getPackageName() : "?"));
2357 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2358 return null;
2359 }
2360 }
2361 }
2362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 }
2364
2365 if (removeExisting) {
2366 if (mInstaller != null) {
2367 int ret = mInstaller.remove(pkgName);
2368 if (ret != 0) {
2369 String msg = "System package " + pkg.packageName
2370 + " could not have data directory erased after signature change.";
2371 reportSettingsProblem(Log.WARN, msg);
2372 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2373 return null;
2374 }
2375 }
2376 Log.w(TAG, "System package " + pkg.packageName
2377 + " signature changed: existing data removed.");
2378 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2379 }
2380
2381 long scanFileTime = scanFile.lastModified();
2382 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2383 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2384 pkg.applicationInfo.processName = fixProcessName(
2385 pkg.applicationInfo.packageName,
2386 pkg.applicationInfo.processName,
2387 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002388 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389
2390 File dataPath;
2391 if (mPlatformPackage == pkg) {
2392 // The system package is special.
2393 dataPath = new File (Environment.getDataDirectory(), "system");
2394 pkg.applicationInfo.dataDir = dataPath.getPath();
2395 } else {
2396 // This is a normal package, need to make its data directory.
2397 dataPath = new File(mAppDataDir, pkgName);
2398 if (dataPath.exists()) {
2399 mOutPermissions[1] = 0;
2400 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2401 if (mOutPermissions[1] == pkg.applicationInfo.uid
2402 || !Process.supportsProcesses()) {
2403 pkg.applicationInfo.dataDir = dataPath.getPath();
2404 } else {
2405 boolean recovered = false;
2406 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2407 // If this is a system app, we can at least delete its
2408 // current data so the application will still work.
2409 if (mInstaller != null) {
2410 int ret = mInstaller.remove(pkgName);
2411 if(ret >= 0) {
2412 // Old data gone!
2413 String msg = "System package " + pkg.packageName
2414 + " has changed from uid: "
2415 + mOutPermissions[1] + " to "
2416 + pkg.applicationInfo.uid + "; old data erased";
2417 reportSettingsProblem(Log.WARN, msg);
2418 recovered = true;
2419
2420 // And now re-install the app.
2421 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2422 pkg.applicationInfo.uid);
2423 if (ret == -1) {
2424 // Ack should not happen!
2425 msg = "System package " + pkg.packageName
2426 + " could not have data directory re-created after delete.";
2427 reportSettingsProblem(Log.WARN, msg);
2428 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2429 return null;
2430 }
2431 }
2432 }
2433 if (!recovered) {
2434 mHasSystemUidErrors = true;
2435 }
2436 }
2437 if (!recovered) {
2438 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2439 + pkg.applicationInfo.uid + "/fs_"
2440 + mOutPermissions[1];
2441 String msg = "Package " + pkg.packageName
2442 + " has mismatched uid: "
2443 + mOutPermissions[1] + " on disk, "
2444 + pkg.applicationInfo.uid + " in settings";
2445 synchronized (mPackages) {
2446 if (!mReportedUidError) {
2447 mReportedUidError = true;
2448 msg = msg + "; read messages:\n"
2449 + mSettings.getReadMessagesLP();
2450 }
2451 reportSettingsProblem(Log.ERROR, msg);
2452 }
2453 }
2454 }
2455 pkg.applicationInfo.dataDir = dataPath.getPath();
2456 } else {
2457 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2458 Log.v(TAG, "Want this data dir: " + dataPath);
2459 //invoke installer to do the actual installation
2460 if (mInstaller != null) {
2461 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2462 pkg.applicationInfo.uid);
2463 if(ret < 0) {
2464 // Error from installer
2465 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2466 return null;
2467 }
2468 } else {
2469 dataPath.mkdirs();
2470 if (dataPath.exists()) {
2471 FileUtils.setPermissions(
2472 dataPath.toString(),
2473 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2474 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2475 }
2476 }
2477 if (dataPath.exists()) {
2478 pkg.applicationInfo.dataDir = dataPath.getPath();
2479 } else {
2480 Log.w(TAG, "Unable to create data directory: " + dataPath);
2481 pkg.applicationInfo.dataDir = null;
2482 }
2483 }
2484 }
2485
2486 // Perform shared library installation and dex validation and
2487 // optimization, if this is not a system app.
2488 if (mInstaller != null) {
2489 String path = scanFile.getPath();
2490 if (scanFileNewer) {
2491 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002492 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2493 if (err != PackageManager.INSTALL_SUCCEEDED) {
2494 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 return null;
2496 }
2497 }
2498
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002499 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2500 pkg.mScanPath = path;
2501
2502 if ((scanMode&SCAN_NO_DEX) == 0) {
2503 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2505 return null;
2506 }
2507 }
2508 }
2509
2510 if (mFactoryTest && pkg.requestedPermissions.contains(
2511 android.Manifest.permission.FACTORY_TEST)) {
2512 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2513 }
2514
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002515 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 if ((scanMode&SCAN_MONITOR) != 0) {
2517 pkg.mPath = destCodeFile.getAbsolutePath();
2518 mAppDirs.put(pkg.mPath, pkg);
2519 }
2520
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002521 // Request the ActivityManager to kill the process(only for existing packages)
2522 // so that we do not end up in a confused state while the user is still using the older
2523 // version of the application while the new one gets installed.
2524 IActivityManager am = ActivityManagerNative.getDefault();
2525 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2526 try {
2527 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2528 pkg.applicationInfo.uid);
2529 } catch (RemoteException e) {
2530 }
2531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002534 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002536 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 int N = pkg.providers.size();
2538 StringBuilder r = null;
2539 int i;
2540 for (i=0; i<N; i++) {
2541 PackageParser.Provider p = pkg.providers.get(i);
2542 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2543 p.info.processName, pkg.applicationInfo.uid);
2544 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2545 p.info.name), p);
2546 p.syncable = p.info.isSyncable;
2547 String names[] = p.info.authority.split(";");
2548 p.info.authority = null;
2549 for (int j = 0; j < names.length; j++) {
2550 if (j == 1 && p.syncable) {
2551 // We only want the first authority for a provider to possibly be
2552 // syncable, so if we already added this provider using a different
2553 // authority clear the syncable flag. We copy the provider before
2554 // changing it because the mProviders object contains a reference
2555 // to a provider that we don't want to change.
2556 // Only do this for the second authority since the resulting provider
2557 // object can be the same for all future authorities for this provider.
2558 p = new PackageParser.Provider(p);
2559 p.syncable = false;
2560 }
2561 if (!mProviders.containsKey(names[j])) {
2562 mProviders.put(names[j], p);
2563 if (p.info.authority == null) {
2564 p.info.authority = names[j];
2565 } else {
2566 p.info.authority = p.info.authority + ";" + names[j];
2567 }
2568 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2569 Log.d(TAG, "Registered content provider: " + names[j] +
2570 ", className = " + p.info.name +
2571 ", isSyncable = " + p.info.isSyncable);
2572 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002573 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 Log.w(TAG, "Skipping provider name " + names[j] +
2575 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002576 "): name already used by "
2577 + ((other != null && other.component != null)
2578 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 }
2580 }
2581 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2582 if (r == null) {
2583 r = new StringBuilder(256);
2584 } else {
2585 r.append(' ');
2586 }
2587 r.append(p.info.name);
2588 }
2589 }
2590 if (r != null) {
2591 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2592 }
2593
2594 N = pkg.services.size();
2595 r = null;
2596 for (i=0; i<N; i++) {
2597 PackageParser.Service s = pkg.services.get(i);
2598 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2599 s.info.processName, pkg.applicationInfo.uid);
2600 mServices.addService(s);
2601 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2602 if (r == null) {
2603 r = new StringBuilder(256);
2604 } else {
2605 r.append(' ');
2606 }
2607 r.append(s.info.name);
2608 }
2609 }
2610 if (r != null) {
2611 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2612 }
2613
2614 N = pkg.receivers.size();
2615 r = null;
2616 for (i=0; i<N; i++) {
2617 PackageParser.Activity a = pkg.receivers.get(i);
2618 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2619 a.info.processName, pkg.applicationInfo.uid);
2620 mReceivers.addActivity(a, "receiver");
2621 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2622 if (r == null) {
2623 r = new StringBuilder(256);
2624 } else {
2625 r.append(' ');
2626 }
2627 r.append(a.info.name);
2628 }
2629 }
2630 if (r != null) {
2631 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2632 }
2633
2634 N = pkg.activities.size();
2635 r = null;
2636 for (i=0; i<N; i++) {
2637 PackageParser.Activity a = pkg.activities.get(i);
2638 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2639 a.info.processName, pkg.applicationInfo.uid);
2640 mActivities.addActivity(a, "activity");
2641 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2642 if (r == null) {
2643 r = new StringBuilder(256);
2644 } else {
2645 r.append(' ');
2646 }
2647 r.append(a.info.name);
2648 }
2649 }
2650 if (r != null) {
2651 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2652 }
2653
2654 N = pkg.permissionGroups.size();
2655 r = null;
2656 for (i=0; i<N; i++) {
2657 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2658 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2659 if (cur == null) {
2660 mPermissionGroups.put(pg.info.name, pg);
2661 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2662 if (r == null) {
2663 r = new StringBuilder(256);
2664 } else {
2665 r.append(' ');
2666 }
2667 r.append(pg.info.name);
2668 }
2669 } else {
2670 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2671 + pg.info.packageName + " ignored: original from "
2672 + cur.info.packageName);
2673 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2674 if (r == null) {
2675 r = new StringBuilder(256);
2676 } else {
2677 r.append(' ');
2678 }
2679 r.append("DUP:");
2680 r.append(pg.info.name);
2681 }
2682 }
2683 }
2684 if (r != null) {
2685 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2686 }
2687
2688 N = pkg.permissions.size();
2689 r = null;
2690 for (i=0; i<N; i++) {
2691 PackageParser.Permission p = pkg.permissions.get(i);
2692 HashMap<String, BasePermission> permissionMap =
2693 p.tree ? mSettings.mPermissionTrees
2694 : mSettings.mPermissions;
2695 p.group = mPermissionGroups.get(p.info.group);
2696 if (p.info.group == null || p.group != null) {
2697 BasePermission bp = permissionMap.get(p.info.name);
2698 if (bp == null) {
2699 bp = new BasePermission(p.info.name, p.info.packageName,
2700 BasePermission.TYPE_NORMAL);
2701 permissionMap.put(p.info.name, bp);
2702 }
2703 if (bp.perm == null) {
2704 if (bp.sourcePackage == null
2705 || bp.sourcePackage.equals(p.info.packageName)) {
2706 BasePermission tree = findPermissionTreeLP(p.info.name);
2707 if (tree == null
2708 || tree.sourcePackage.equals(p.info.packageName)) {
2709 bp.perm = p;
2710 bp.uid = pkg.applicationInfo.uid;
2711 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2712 if (r == null) {
2713 r = new StringBuilder(256);
2714 } else {
2715 r.append(' ');
2716 }
2717 r.append(p.info.name);
2718 }
2719 } else {
2720 Log.w(TAG, "Permission " + p.info.name + " from package "
2721 + p.info.packageName + " ignored: base tree "
2722 + tree.name + " is from package "
2723 + tree.sourcePackage);
2724 }
2725 } else {
2726 Log.w(TAG, "Permission " + p.info.name + " from package "
2727 + p.info.packageName + " ignored: original from "
2728 + bp.sourcePackage);
2729 }
2730 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2731 if (r == null) {
2732 r = new StringBuilder(256);
2733 } else {
2734 r.append(' ');
2735 }
2736 r.append("DUP:");
2737 r.append(p.info.name);
2738 }
2739 } else {
2740 Log.w(TAG, "Permission " + p.info.name + " from package "
2741 + p.info.packageName + " ignored: no group "
2742 + p.group);
2743 }
2744 }
2745 if (r != null) {
2746 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2747 }
2748
2749 N = pkg.instrumentation.size();
2750 r = null;
2751 for (i=0; i<N; i++) {
2752 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2753 a.info.packageName = pkg.applicationInfo.packageName;
2754 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2755 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2756 a.info.dataDir = pkg.applicationInfo.dataDir;
2757 mInstrumentation.put(a.component, a);
2758 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2759 if (r == null) {
2760 r = new StringBuilder(256);
2761 } else {
2762 r.append(' ');
2763 }
2764 r.append(a.info.name);
2765 }
2766 }
2767 if (r != null) {
2768 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2769 }
2770
Dianne Hackborn854060af2009-07-09 18:14:31 -07002771 if (pkg.protectedBroadcasts != null) {
2772 N = pkg.protectedBroadcasts.size();
2773 for (i=0; i<N; i++) {
2774 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2775 }
2776 }
2777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 pkgSetting.setTimeStamp(scanFileTime);
2779 }
2780
2781 return pkg;
2782 }
2783
Dianne Hackbornb1811182009-05-21 15:45:42 -07002784 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2785 File dataPath, File scanFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002787 final String sharedLibraryABI = Build.CPU_ABI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002788 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2789 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2790 final String sharedLibrarySuffix = ".so";
Dianne Hackbornb1811182009-05-21 15:45:42 -07002791 boolean hasNativeCode = false;
2792 boolean installedNativeCode = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 try {
2794 ZipFile zipFile = new ZipFile(scanFile);
2795 Enumeration<ZipEntry> entries =
2796 (Enumeration<ZipEntry>) zipFile.entries();
2797
2798 while (entries.hasMoreElements()) {
2799 ZipEntry entry = entries.nextElement();
2800 if (entry.isDirectory()) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002801 if (!hasNativeCode && entry.getName().startsWith("lib")) {
2802 hasNativeCode = true;
2803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 continue;
2805 }
2806 String entryName = entry.getName();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002807 if (entryName.startsWith("lib/")) {
2808 hasNativeCode = true;
2809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002810 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2811 && entryName.endsWith(sharedLibrarySuffix))) {
2812 continue;
2813 }
2814 String libFileName = entryName.substring(
2815 apkLibraryDirectory.length());
2816 if (libFileName.contains("/")
2817 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2818 continue;
2819 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002820
2821 installedNativeCode = true;
2822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2824 File.separator + libFileName;
2825 File sharedLibraryFile = new File(sharedLibraryFilePath);
2826 if (! sharedLibraryFile.exists() ||
2827 sharedLibraryFile.length() != entry.getSize() ||
2828 sharedLibraryFile.lastModified() != entry.getTime()) {
2829 if (Config.LOGD) {
2830 Log.d(TAG, "Caching shared lib " + entry.getName());
2831 }
2832 if (mInstaller == null) {
2833 sharedLibraryDir.mkdir();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 }
2835 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2836 sharedLibraryFile);
2837 }
2838 }
2839 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002840 Log.w(TAG, "Failed to cache package shared libs", e);
2841 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002843
2844 if (hasNativeCode && !installedNativeCode) {
2845 Log.w(TAG, "Install failed: .apk has native code but none for arch "
2846 + Build.CPU_ABI);
2847 return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
2848 }
2849
2850 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
2853 private void cacheSharedLibLI(PackageParser.Package pkg,
2854 ZipFile zipFile, ZipEntry entry,
2855 File sharedLibraryDir,
2856 File sharedLibraryFile) throws IOException {
2857 InputStream inputStream = zipFile.getInputStream(entry);
2858 try {
2859 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2860 String tempFilePath = tempFile.getPath();
2861 // XXX package manager can't change owner, so the lib files for
2862 // now need to be left as world readable and owned by the system.
2863 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2864 ! tempFile.setLastModified(entry.getTime()) ||
2865 FileUtils.setPermissions(tempFilePath,
2866 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2867 |FileUtils.S_IROTH, -1, -1) != 0 ||
2868 ! tempFile.renameTo(sharedLibraryFile)) {
2869 // Failed to properly write file.
2870 tempFile.delete();
2871 throw new IOException("Couldn't create cached shared lib "
2872 + sharedLibraryFile + " in " + sharedLibraryDir);
2873 }
2874 } finally {
2875 inputStream.close();
2876 }
2877 }
2878
2879 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2880 if (chatty && Config.LOGD) Log.d(
2881 TAG, "Removing package " + pkg.applicationInfo.packageName );
2882
2883 synchronized (mPackages) {
2884 if (pkg.mPreferredOrder > 0) {
2885 mSettings.mPreferredPackages.remove(pkg);
2886 pkg.mPreferredOrder = 0;
2887 updatePreferredIndicesLP();
2888 }
2889
2890 clearPackagePreferredActivitiesLP(pkg.packageName);
2891
2892 mPackages.remove(pkg.applicationInfo.packageName);
2893 if (pkg.mPath != null) {
2894 mAppDirs.remove(pkg.mPath);
2895 }
2896
2897 PackageSetting ps = (PackageSetting)pkg.mExtras;
2898 if (ps != null && ps.sharedUser != null) {
2899 // XXX don't do this until the data is removed.
2900 if (false) {
2901 ps.sharedUser.packages.remove(ps);
2902 if (ps.sharedUser.packages.size() == 0) {
2903 // Remove.
2904 }
2905 }
2906 }
2907
2908 int N = pkg.providers.size();
2909 StringBuilder r = null;
2910 int i;
2911 for (i=0; i<N; i++) {
2912 PackageParser.Provider p = pkg.providers.get(i);
2913 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2914 p.info.name));
2915 if (p.info.authority == null) {
2916
2917 /* The is another ContentProvider with this authority when
2918 * this app was installed so this authority is null,
2919 * Ignore it as we don't have to unregister the provider.
2920 */
2921 continue;
2922 }
2923 String names[] = p.info.authority.split(";");
2924 for (int j = 0; j < names.length; j++) {
2925 if (mProviders.get(names[j]) == p) {
2926 mProviders.remove(names[j]);
2927 if (chatty && Config.LOGD) Log.d(
2928 TAG, "Unregistered content provider: " + names[j] +
2929 ", className = " + p.info.name +
2930 ", isSyncable = " + p.info.isSyncable);
2931 }
2932 }
2933 if (chatty) {
2934 if (r == null) {
2935 r = new StringBuilder(256);
2936 } else {
2937 r.append(' ');
2938 }
2939 r.append(p.info.name);
2940 }
2941 }
2942 if (r != null) {
2943 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2944 }
2945
2946 N = pkg.services.size();
2947 r = null;
2948 for (i=0; i<N; i++) {
2949 PackageParser.Service s = pkg.services.get(i);
2950 mServices.removeService(s);
2951 if (chatty) {
2952 if (r == null) {
2953 r = new StringBuilder(256);
2954 } else {
2955 r.append(' ');
2956 }
2957 r.append(s.info.name);
2958 }
2959 }
2960 if (r != null) {
2961 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2962 }
2963
2964 N = pkg.receivers.size();
2965 r = null;
2966 for (i=0; i<N; i++) {
2967 PackageParser.Activity a = pkg.receivers.get(i);
2968 mReceivers.removeActivity(a, "receiver");
2969 if (chatty) {
2970 if (r == null) {
2971 r = new StringBuilder(256);
2972 } else {
2973 r.append(' ');
2974 }
2975 r.append(a.info.name);
2976 }
2977 }
2978 if (r != null) {
2979 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2980 }
2981
2982 N = pkg.activities.size();
2983 r = null;
2984 for (i=0; i<N; i++) {
2985 PackageParser.Activity a = pkg.activities.get(i);
2986 mActivities.removeActivity(a, "activity");
2987 if (chatty) {
2988 if (r == null) {
2989 r = new StringBuilder(256);
2990 } else {
2991 r.append(' ');
2992 }
2993 r.append(a.info.name);
2994 }
2995 }
2996 if (r != null) {
2997 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2998 }
2999
3000 N = pkg.permissions.size();
3001 r = null;
3002 for (i=0; i<N; i++) {
3003 PackageParser.Permission p = pkg.permissions.get(i);
3004 boolean tree = false;
3005 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3006 if (bp == null) {
3007 tree = true;
3008 bp = mSettings.mPermissionTrees.get(p.info.name);
3009 }
3010 if (bp != null && bp.perm == p) {
3011 if (bp.type != BasePermission.TYPE_BUILTIN) {
3012 if (tree) {
3013 mSettings.mPermissionTrees.remove(p.info.name);
3014 } else {
3015 mSettings.mPermissions.remove(p.info.name);
3016 }
3017 } else {
3018 bp.perm = null;
3019 }
3020 if (chatty) {
3021 if (r == null) {
3022 r = new StringBuilder(256);
3023 } else {
3024 r.append(' ');
3025 }
3026 r.append(p.info.name);
3027 }
3028 }
3029 }
3030 if (r != null) {
3031 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3032 }
3033
3034 N = pkg.instrumentation.size();
3035 r = null;
3036 for (i=0; i<N; i++) {
3037 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3038 mInstrumentation.remove(a.component);
3039 if (chatty) {
3040 if (r == null) {
3041 r = new StringBuilder(256);
3042 } else {
3043 r.append(' ');
3044 }
3045 r.append(a.info.name);
3046 }
3047 }
3048 if (r != null) {
3049 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3050 }
3051 }
3052 }
3053
3054 private static final boolean isPackageFilename(String name) {
3055 return name != null && name.endsWith(".apk");
3056 }
3057
3058 private void updatePermissionsLP() {
3059 // Make sure there are no dangling permission trees.
3060 Iterator<BasePermission> it = mSettings.mPermissionTrees
3061 .values().iterator();
3062 while (it.hasNext()) {
3063 BasePermission bp = it.next();
3064 if (bp.perm == null) {
3065 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3066 + " from package " + bp.sourcePackage);
3067 it.remove();
3068 }
3069 }
3070
3071 // Make sure all dynamic permissions have been assigned to a package,
3072 // and make sure there are no dangling permissions.
3073 it = mSettings.mPermissions.values().iterator();
3074 while (it.hasNext()) {
3075 BasePermission bp = it.next();
3076 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3077 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3078 + bp.name + " pkg=" + bp.sourcePackage
3079 + " info=" + bp.pendingInfo);
3080 if (bp.perm == null && bp.pendingInfo != null) {
3081 BasePermission tree = findPermissionTreeLP(bp.name);
3082 if (tree != null) {
3083 bp.perm = new PackageParser.Permission(tree.perm.owner,
3084 new PermissionInfo(bp.pendingInfo));
3085 bp.perm.info.packageName = tree.perm.info.packageName;
3086 bp.perm.info.name = bp.name;
3087 bp.uid = tree.uid;
3088 }
3089 }
3090 }
3091 if (bp.perm == null) {
3092 Log.w(TAG, "Removing dangling permission: " + bp.name
3093 + " from package " + bp.sourcePackage);
3094 it.remove();
3095 }
3096 }
3097
3098 // Now update the permissions for all packages, in particular
3099 // replace the granted permissions of the system packages.
3100 for (PackageParser.Package pkg : mPackages.values()) {
3101 grantPermissionsLP(pkg, false);
3102 }
3103 }
3104
3105 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3106 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3107 if (ps == null) {
3108 return;
3109 }
3110 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3111 boolean addedPermission = false;
3112
3113 if (replace) {
3114 ps.permissionsFixed = false;
3115 if (gp == ps) {
3116 gp.grantedPermissions.clear();
3117 gp.gids = mGlobalGids;
3118 }
3119 }
3120
3121 if (gp.gids == null) {
3122 gp.gids = mGlobalGids;
3123 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07003124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 final int N = pkg.requestedPermissions.size();
3126 for (int i=0; i<N; i++) {
3127 String name = pkg.requestedPermissions.get(i);
3128 BasePermission bp = mSettings.mPermissions.get(name);
3129 PackageParser.Permission p = bp != null ? bp.perm : null;
3130 if (false) {
3131 if (gp != ps) {
3132 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3133 + ": " + p);
3134 }
3135 }
3136 if (p != null) {
3137 final String perm = p.info.name;
3138 boolean allowed;
3139 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3140 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3141 allowed = true;
3142 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3143 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003144 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003146 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 == PackageManager.SIGNATURE_MATCH);
3148 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3149 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3150 // For updated system applications, the signatureOrSystem permission
3151 // is granted only if it had been defined by the original application.
3152 if ((pkg.applicationInfo.flags
3153 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3154 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3155 if(sysPs.grantedPermissions.contains(perm)) {
3156 allowed = true;
3157 } else {
3158 allowed = false;
3159 }
3160 } else {
3161 allowed = true;
3162 }
3163 }
3164 }
3165 } else {
3166 allowed = false;
3167 }
3168 if (false) {
3169 if (gp != ps) {
3170 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3171 }
3172 }
3173 if (allowed) {
3174 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3175 && ps.permissionsFixed) {
3176 // If this is an existing, non-system package, then
3177 // we can't add any new permissions to it.
3178 if (!gp.loadedPermissions.contains(perm)) {
3179 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003180 // Except... if this is a permission that was added
3181 // to the platform (note: need to only do this when
3182 // updating the platform).
3183 final int NP = PackageParser.NEW_PERMISSIONS.length;
3184 for (int ip=0; ip<NP; ip++) {
3185 final PackageParser.NewPermissionInfo npi
3186 = PackageParser.NEW_PERMISSIONS[ip];
3187 if (npi.name.equals(perm)
3188 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3189 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003190 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003191 + pkg.packageName);
3192 break;
3193 }
3194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 }
3196 }
3197 if (allowed) {
3198 if (!gp.grantedPermissions.contains(perm)) {
3199 addedPermission = true;
3200 gp.grantedPermissions.add(perm);
3201 gp.gids = appendInts(gp.gids, bp.gids);
3202 }
3203 } else {
3204 Log.w(TAG, "Not granting permission " + perm
3205 + " to package " + pkg.packageName
3206 + " because it was previously installed without");
3207 }
3208 } else {
3209 Log.w(TAG, "Not granting permission " + perm
3210 + " to package " + pkg.packageName
3211 + " (protectionLevel=" + p.info.protectionLevel
3212 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3213 + ")");
3214 }
3215 } else {
3216 Log.w(TAG, "Unknown permission " + name
3217 + " in package " + pkg.packageName);
3218 }
3219 }
3220
3221 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003222 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3223 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 // This is the first that we have heard about this package, so the
3225 // permissions we have now selected are fixed until explicitly
3226 // changed.
3227 ps.permissionsFixed = true;
3228 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3229 }
3230 }
3231
3232 private final class ActivityIntentResolver
3233 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003234 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003236 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 }
3238
Mihai Preda074edef2009-05-18 17:13:31 +02003239 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003241 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3243 }
3244
Mihai Predaeae850c2009-05-13 10:13:48 +02003245 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3246 ArrayList<PackageParser.Activity> packageActivities) {
3247 if (packageActivities == null) {
3248 return null;
3249 }
3250 mFlags = flags;
3251 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3252 int N = packageActivities.size();
3253 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3254 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003255
3256 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003257 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003258 intentFilters = packageActivities.get(i).intents;
3259 if (intentFilters != null && intentFilters.size() > 0) {
3260 listCut.add(intentFilters);
3261 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003262 }
3263 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3264 }
3265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003266 public final void addActivity(PackageParser.Activity a, String type) {
3267 mActivities.put(a.component, a);
3268 if (SHOW_INFO || Config.LOGV) Log.v(
3269 TAG, " " + type + " " +
3270 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3271 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3272 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003273 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3275 if (SHOW_INFO || Config.LOGV) {
3276 Log.v(TAG, " IntentFilter:");
3277 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3278 }
3279 if (!intent.debugCheck()) {
3280 Log.w(TAG, "==> For Activity " + a.info.name);
3281 }
3282 addFilter(intent);
3283 }
3284 }
3285
3286 public final void removeActivity(PackageParser.Activity a, String type) {
3287 mActivities.remove(a.component);
3288 if (SHOW_INFO || Config.LOGV) Log.v(
3289 TAG, " " + type + " " +
3290 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3291 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3292 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003293 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3295 if (SHOW_INFO || Config.LOGV) {
3296 Log.v(TAG, " IntentFilter:");
3297 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3298 }
3299 removeFilter(intent);
3300 }
3301 }
3302
3303 @Override
3304 protected boolean allowFilterResult(
3305 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3306 ActivityInfo filterAi = filter.activity.info;
3307 for (int i=dest.size()-1; i>=0; i--) {
3308 ActivityInfo destAi = dest.get(i).activityInfo;
3309 if (destAi.name == filterAi.name
3310 && destAi.packageName == filterAi.packageName) {
3311 return false;
3312 }
3313 }
3314 return true;
3315 }
3316
3317 @Override
3318 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3319 int match) {
3320 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3321 return null;
3322 }
3323 final PackageParser.Activity activity = info.activity;
3324 if (mSafeMode && (activity.info.applicationInfo.flags
3325 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3326 return null;
3327 }
3328 final ResolveInfo res = new ResolveInfo();
3329 res.activityInfo = PackageParser.generateActivityInfo(activity,
3330 mFlags);
3331 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3332 res.filter = info;
3333 }
3334 res.priority = info.getPriority();
3335 res.preferredOrder = activity.owner.mPreferredOrder;
3336 //System.out.println("Result: " + res.activityInfo.className +
3337 // " = " + res.priority);
3338 res.match = match;
3339 res.isDefault = info.hasDefault;
3340 res.labelRes = info.labelRes;
3341 res.nonLocalizedLabel = info.nonLocalizedLabel;
3342 res.icon = info.icon;
3343 return res;
3344 }
3345
3346 @Override
3347 protected void sortResults(List<ResolveInfo> results) {
3348 Collections.sort(results, mResolvePrioritySorter);
3349 }
3350
3351 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003352 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003354 out.print(prefix); out.print(
3355 Integer.toHexString(System.identityHashCode(filter.activity)));
3356 out.print(' ');
3357 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 }
3359
3360// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3361// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3362// final List<ResolveInfo> retList = Lists.newArrayList();
3363// while (i.hasNext()) {
3364// final ResolveInfo resolveInfo = i.next();
3365// if (isEnabledLP(resolveInfo.activityInfo)) {
3366// retList.add(resolveInfo);
3367// }
3368// }
3369// return retList;
3370// }
3371
3372 // Keys are String (activity class name), values are Activity.
3373 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3374 = new HashMap<ComponentName, PackageParser.Activity>();
3375 private int mFlags;
3376 }
3377
3378 private final class ServiceIntentResolver
3379 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003380 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003382 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 }
3384
Mihai Preda074edef2009-05-18 17:13:31 +02003385 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003387 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3389 }
3390
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003391 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3392 ArrayList<PackageParser.Service> packageServices) {
3393 if (packageServices == null) {
3394 return null;
3395 }
3396 mFlags = flags;
3397 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3398 int N = packageServices.size();
3399 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3400 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3401
3402 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3403 for (int i = 0; i < N; ++i) {
3404 intentFilters = packageServices.get(i).intents;
3405 if (intentFilters != null && intentFilters.size() > 0) {
3406 listCut.add(intentFilters);
3407 }
3408 }
3409 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3410 }
3411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 public final void addService(PackageParser.Service s) {
3413 mServices.put(s.component, s);
3414 if (SHOW_INFO || Config.LOGV) Log.v(
3415 TAG, " " + (s.info.nonLocalizedLabel != null
3416 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3417 if (SHOW_INFO || Config.LOGV) Log.v(
3418 TAG, " Class=" + s.info.name);
3419 int NI = s.intents.size();
3420 int j;
3421 for (j=0; j<NI; j++) {
3422 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3423 if (SHOW_INFO || Config.LOGV) {
3424 Log.v(TAG, " IntentFilter:");
3425 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3426 }
3427 if (!intent.debugCheck()) {
3428 Log.w(TAG, "==> For Service " + s.info.name);
3429 }
3430 addFilter(intent);
3431 }
3432 }
3433
3434 public final void removeService(PackageParser.Service s) {
3435 mServices.remove(s.component);
3436 if (SHOW_INFO || Config.LOGV) Log.v(
3437 TAG, " " + (s.info.nonLocalizedLabel != null
3438 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3439 if (SHOW_INFO || Config.LOGV) Log.v(
3440 TAG, " Class=" + s.info.name);
3441 int NI = s.intents.size();
3442 int j;
3443 for (j=0; j<NI; j++) {
3444 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3445 if (SHOW_INFO || Config.LOGV) {
3446 Log.v(TAG, " IntentFilter:");
3447 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3448 }
3449 removeFilter(intent);
3450 }
3451 }
3452
3453 @Override
3454 protected boolean allowFilterResult(
3455 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3456 ServiceInfo filterSi = filter.service.info;
3457 for (int i=dest.size()-1; i>=0; i--) {
3458 ServiceInfo destAi = dest.get(i).serviceInfo;
3459 if (destAi.name == filterSi.name
3460 && destAi.packageName == filterSi.packageName) {
3461 return false;
3462 }
3463 }
3464 return true;
3465 }
3466
3467 @Override
3468 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3469 int match) {
3470 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3471 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3472 return null;
3473 }
3474 final PackageParser.Service service = info.service;
3475 if (mSafeMode && (service.info.applicationInfo.flags
3476 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3477 return null;
3478 }
3479 final ResolveInfo res = new ResolveInfo();
3480 res.serviceInfo = PackageParser.generateServiceInfo(service,
3481 mFlags);
3482 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3483 res.filter = filter;
3484 }
3485 res.priority = info.getPriority();
3486 res.preferredOrder = service.owner.mPreferredOrder;
3487 //System.out.println("Result: " + res.activityInfo.className +
3488 // " = " + res.priority);
3489 res.match = match;
3490 res.isDefault = info.hasDefault;
3491 res.labelRes = info.labelRes;
3492 res.nonLocalizedLabel = info.nonLocalizedLabel;
3493 res.icon = info.icon;
3494 return res;
3495 }
3496
3497 @Override
3498 protected void sortResults(List<ResolveInfo> results) {
3499 Collections.sort(results, mResolvePrioritySorter);
3500 }
3501
3502 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003503 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003505 out.print(prefix); out.print(
3506 Integer.toHexString(System.identityHashCode(filter.service)));
3507 out.print(' ');
3508 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 }
3510
3511// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3512// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3513// final List<ResolveInfo> retList = Lists.newArrayList();
3514// while (i.hasNext()) {
3515// final ResolveInfo resolveInfo = (ResolveInfo) i;
3516// if (isEnabledLP(resolveInfo.serviceInfo)) {
3517// retList.add(resolveInfo);
3518// }
3519// }
3520// return retList;
3521// }
3522
3523 // Keys are String (activity class name), values are Activity.
3524 private final HashMap<ComponentName, PackageParser.Service> mServices
3525 = new HashMap<ComponentName, PackageParser.Service>();
3526 private int mFlags;
3527 };
3528
3529 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3530 new Comparator<ResolveInfo>() {
3531 public int compare(ResolveInfo r1, ResolveInfo r2) {
3532 int v1 = r1.priority;
3533 int v2 = r2.priority;
3534 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3535 if (v1 != v2) {
3536 return (v1 > v2) ? -1 : 1;
3537 }
3538 v1 = r1.preferredOrder;
3539 v2 = r2.preferredOrder;
3540 if (v1 != v2) {
3541 return (v1 > v2) ? -1 : 1;
3542 }
3543 if (r1.isDefault != r2.isDefault) {
3544 return r1.isDefault ? -1 : 1;
3545 }
3546 v1 = r1.match;
3547 v2 = r2.match;
3548 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3549 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3550 }
3551 };
3552
3553 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3554 new Comparator<ProviderInfo>() {
3555 public int compare(ProviderInfo p1, ProviderInfo p2) {
3556 final int v1 = p1.initOrder;
3557 final int v2 = p2.initOrder;
3558 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3559 }
3560 };
3561
3562 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3563 IActivityManager am = ActivityManagerNative.getDefault();
3564 if (am != null) {
3565 try {
3566 final Intent intent = new Intent(action,
3567 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3568 if (extras != null) {
3569 intent.putExtras(extras);
3570 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003571 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 am.broadcastIntent(
3573 null, intent,
3574 null, null, 0, null, null, null, false, false);
3575 } catch (RemoteException ex) {
3576 }
3577 }
3578 }
3579
3580 private final class AppDirObserver extends FileObserver {
3581 public AppDirObserver(String path, int mask, boolean isrom) {
3582 super(path, mask);
3583 mRootDir = path;
3584 mIsRom = isrom;
3585 }
3586
3587 public void onEvent(int event, String path) {
3588 String removedPackage = null;
3589 int removedUid = -1;
3590 String addedPackage = null;
3591 int addedUid = -1;
3592
3593 synchronized (mInstallLock) {
3594 String fullPathStr = null;
3595 File fullPath = null;
3596 if (path != null) {
3597 fullPath = new File(mRootDir, path);
3598 fullPathStr = fullPath.getPath();
3599 }
3600
3601 if (Config.LOGV) Log.v(
3602 TAG, "File " + fullPathStr + " changed: "
3603 + Integer.toHexString(event));
3604
3605 if (!isPackageFilename(path)) {
3606 if (Config.LOGV) Log.v(
3607 TAG, "Ignoring change of non-package file: " + fullPathStr);
3608 return;
3609 }
3610
3611 if ((event&REMOVE_EVENTS) != 0) {
3612 synchronized (mInstallLock) {
3613 PackageParser.Package p = mAppDirs.get(fullPathStr);
3614 if (p != null) {
3615 removePackageLI(p, true);
3616 removedPackage = p.applicationInfo.packageName;
3617 removedUid = p.applicationInfo.uid;
3618 }
3619 }
3620 }
3621
3622 if ((event&ADD_EVENTS) != 0) {
3623 PackageParser.Package p = mAppDirs.get(fullPathStr);
3624 if (p == null) {
3625 p = scanPackageLI(fullPath, fullPath, fullPath,
3626 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3627 PackageParser.PARSE_CHATTY |
3628 PackageParser.PARSE_MUST_BE_APK,
3629 SCAN_MONITOR);
3630 if (p != null) {
3631 synchronized (mPackages) {
3632 grantPermissionsLP(p, false);
3633 }
3634 addedPackage = p.applicationInfo.packageName;
3635 addedUid = p.applicationInfo.uid;
3636 }
3637 }
3638 }
3639
3640 synchronized (mPackages) {
3641 mSettings.writeLP();
3642 }
3643 }
3644
3645 if (removedPackage != null) {
3646 Bundle extras = new Bundle(1);
3647 extras.putInt(Intent.EXTRA_UID, removedUid);
3648 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3649 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3650 }
3651 if (addedPackage != null) {
3652 Bundle extras = new Bundle(1);
3653 extras.putInt(Intent.EXTRA_UID, addedUid);
3654 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3655 }
3656 }
3657
3658 private final String mRootDir;
3659 private final boolean mIsRom;
3660 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 /* Called when a downloaded package installation has been confirmed by the user */
3663 public void installPackage(
3664 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003665 installPackage(packageURI, observer, flags, null);
3666 }
3667
3668 /* Called when a downloaded package installation has been confirmed by the user */
3669 public void installPackage(
3670 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3671 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 mContext.enforceCallingOrSelfPermission(
3673 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 // Queue up an async operation since the package installation may take a little while.
3676 mHandler.post(new Runnable() {
3677 public void run() {
3678 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003679 // Result object to be returned
3680 PackageInstalledInfo res = new PackageInstalledInfo();
3681 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3682 res.uid = -1;
3683 res.pkg = null;
3684 res.removedInfo = new PackageRemovedInfo();
3685 // Make a temporary copy of file from given packageURI
3686 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3687 if (tmpPackageFile != null) {
3688 synchronized (mInstallLock) {
3689 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 }
3692 if (observer != null) {
3693 try {
3694 observer.packageInstalled(res.name, res.returnCode);
3695 } catch (RemoteException e) {
3696 Log.i(TAG, "Observer no longer exists.");
3697 }
3698 }
3699 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3700 // call appears in the synchronized block above.
3701 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3702 res.removedInfo.sendBroadcast(false, true);
3703 Bundle extras = new Bundle(1);
3704 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003705 final boolean update = res.removedInfo.removedPackage != null;
3706 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3708 }
3709 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3710 res.pkg.applicationInfo.packageName,
3711 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003712 if (update) {
3713 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3714 res.pkg.applicationInfo.packageName,
3715 extras);
3716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 }
3718 Runtime.getRuntime().gc();
3719 }
3720 });
3721 }
3722
3723 class PackageInstalledInfo {
3724 String name;
3725 int uid;
3726 PackageParser.Package pkg;
3727 int returnCode;
3728 PackageRemovedInfo removedInfo;
3729 }
3730
3731 /*
3732 * Install a non-existing package.
3733 */
3734 private void installNewPackageLI(String pkgName,
3735 File tmpPackageFile,
3736 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003737 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003738 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003739 // Remember this for later, in case we need to rollback this install
3740 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3741 res.name = pkgName;
3742 synchronized(mPackages) {
3743 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3744 // Don't allow installation over an existing package with the same name.
3745 Log.w(TAG, "Attempt to re-install " + pkgName
3746 + " without first uninstalling.");
3747 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3748 return;
3749 }
3750 }
3751 if (destPackageFile.exists()) {
3752 // It's safe to do this because we know (from the above check) that the file
3753 // isn't currently used for an installed package.
3754 destPackageFile.delete();
3755 }
3756 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3757 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3758 destResourceFile, pkg, 0,
3759 SCAN_MONITOR | SCAN_FORCE_DEX
3760 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003761 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3762 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 if (newPackage == null) {
3764 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3765 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3766 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3767 }
3768 } else {
3769 updateSettingsLI(pkgName, tmpPackageFile,
3770 destFilePath, destPackageFile,
3771 destResourceFile, pkg,
3772 newPackage,
3773 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003774 forwardLocked,
3775 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 res);
3777 // delete the partially installed application. the data directory will have to be
3778 // restored if it was already existing
3779 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3780 // remove package from internal structures. Note that we want deletePackageX to
3781 // delete the package data and cache directories that it created in
3782 // scanPackageLocked, unless those directories existed before we even tried to
3783 // install.
3784 deletePackageLI(
3785 pkgName, true,
3786 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3787 res.removedInfo);
3788 }
3789 }
3790 }
3791
3792 private void replacePackageLI(String pkgName,
3793 File tmpPackageFile,
3794 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003795 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003796 String installerPackageName, PackageInstalledInfo res) {
3797
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003798 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 // First find the old package info and check signatures
3800 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003801 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003802 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3803 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3805 return;
3806 }
3807 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003808 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003810 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003812 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003813 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003815 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003816 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003817 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 }
3819 }
3820
3821 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3822 File tmpPackageFile,
3823 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003824 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003825 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 PackageParser.Package newPackage = null;
3827 String pkgName = deletedPackage.packageName;
3828 boolean deletedPkg = true;
3829 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003830
3831 String oldInstallerPackageName = null;
3832 synchronized (mPackages) {
3833 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3834 }
3835
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003836 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 // First delete the existing package while retaining the data directory
3838 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3839 res.removedInfo)) {
3840 // If the existing package was'nt successfully deleted
3841 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3842 deletedPkg = false;
3843 } else {
3844 // Successfully deleted the old package. Now proceed with re-installation
3845 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3846 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3847 destResourceFile, pkg, parseFlags,
3848 SCAN_MONITOR | SCAN_FORCE_DEX
3849 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003850 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3851 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 if (newPackage == null) {
3853 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3854 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3855 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3856 }
3857 } else {
3858 updateSettingsLI(pkgName, tmpPackageFile,
3859 destFilePath, destPackageFile,
3860 destResourceFile, pkg,
3861 newPackage,
3862 true,
3863 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003864 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 res);
3866 updatedSettings = true;
3867 }
3868 }
3869
3870 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3871 // If we deleted an exisiting package, the old source and resource files that we
3872 // were keeping around in case we needed them (see below) can now be deleted
3873 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3874 final ApplicationInfo installedPackageAppInfo =
3875 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003876 deletePackageResourcesLI(pkgName,
3877 !deletedPackageAppInfo.sourceDir
3878 .equals(installedPackageAppInfo.sourceDir)
3879 ? deletedPackageAppInfo.sourceDir : null,
3880 !deletedPackageAppInfo.publicSourceDir
3881 .equals(installedPackageAppInfo.publicSourceDir)
3882 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 //update signature on the new package setting
3884 //this should always succeed, since we checked the
3885 //signature earlier.
3886 synchronized(mPackages) {
3887 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3888 parseFlags, true);
3889 }
3890 } else {
3891 // remove package from internal structures. Note that we want deletePackageX to
3892 // delete the package data and cache directories that it created in
3893 // scanPackageLocked, unless those directories existed before we even tried to
3894 // install.
3895 if(updatedSettings) {
3896 deletePackageLI(
3897 pkgName, true,
3898 PackageManager.DONT_DELETE_DATA,
3899 res.removedInfo);
3900 }
3901 // Since we failed to install the new package we need to restore the old
3902 // package that we deleted.
3903 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003904 File restoreFile = new File(deletedPackage.mPath);
3905 if (restoreFile == null) {
3906 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
3907 return;
3908 }
3909 File restoreTmpFile = createTempPackageFile();
3910 if (restoreTmpFile == null) {
3911 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
3912 return;
3913 }
3914 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
3915 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
3916 return;
3917 }
3918 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
3919 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003921 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003923 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003924 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
3925 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3926 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
3927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
3929 }
3930 }
3931
3932 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3933 File tmpPackageFile,
3934 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003935 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003936 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 PackageParser.Package newPackage = null;
3938 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003939 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 PackageParser.PARSE_IS_SYSTEM;
3941 String packageName = deletedPackage.packageName;
3942 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3943 if (packageName == null) {
3944 Log.w(TAG, "Attempt to delete null packageName.");
3945 return;
3946 }
3947 PackageParser.Package oldPkg;
3948 PackageSetting oldPkgSetting;
3949 synchronized (mPackages) {
3950 oldPkg = mPackages.get(packageName);
3951 oldPkgSetting = mSettings.mPackages.get(packageName);
3952 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3953 (oldPkgSetting == null)) {
3954 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3955 return;
3956 }
3957 }
3958 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3959 res.removedInfo.removedPackage = packageName;
3960 // Remove existing system package
3961 removePackageLI(oldPkg, true);
3962 synchronized (mPackages) {
3963 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3964 }
3965
3966 // Successfully disabled the old package. Now proceed with re-installation
3967 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3968 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3969 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3970 destResourceFile, pkg, parseFlags,
3971 SCAN_MONITOR | SCAN_FORCE_DEX
3972 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003973 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3974 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 if (newPackage == null) {
3976 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3977 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3978 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3979 }
3980 } else {
3981 updateSettingsLI(packageName, tmpPackageFile,
3982 destFilePath, destPackageFile,
3983 destResourceFile, pkg,
3984 newPackage,
3985 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003986 forwardLocked,
3987 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 res);
3989 updatedSettings = true;
3990 }
3991
3992 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3993 //update signature on the new package setting
3994 //this should always succeed, since we checked the
3995 //signature earlier.
3996 synchronized(mPackages) {
3997 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3998 parseFlags, true);
3999 }
4000 } else {
4001 // Re installation failed. Restore old information
4002 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004003 if (newPackage != null) {
4004 removePackageLI(newPackage, true);
4005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 // Add back the old system package
4007 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
4008 oldPkgSetting.resourcePath,
4009 oldPkg, parseFlags,
4010 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004011 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 // Restore the old system information in Settings
4013 synchronized(mPackages) {
4014 if(updatedSettings) {
4015 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004016 mSettings.setInstallerPackageName(packageName,
4017 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 }
4019 mSettings.writeLP();
4020 }
4021 }
4022 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 private void updateSettingsLI(String pkgName, File tmpPackageFile,
4025 String destFilePath, File destPackageFile,
4026 File destResourceFile,
4027 PackageParser.Package pkg,
4028 PackageParser.Package newPackage,
4029 boolean replacingExistingPackage,
4030 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02004031 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 synchronized (mPackages) {
4033 //write settings. the installStatus will be incomplete at this stage.
4034 //note that the new package setting would have already been
4035 //added to mPackages. It hasn't been persisted yet.
4036 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4037 mSettings.writeLP();
4038 }
4039
4040 int retCode = 0;
4041 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4042 retCode = mInstaller.movedex(tmpPackageFile.toString(),
4043 destPackageFile.toString());
4044 if (retCode != 0) {
4045 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
4046 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4047 return;
4048 }
4049 }
4050 // XXX There are probably some big issues here: upon doing
4051 // the rename, we have reached the point of no return (the
4052 // original .apk is gone!), so we can't fail. Yet... we can.
4053 if (!tmpPackageFile.renameTo(destPackageFile)) {
4054 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
4055 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4056 } else {
4057 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4058 destResourceFile,
4059 forwardLocked);
4060 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4061 return;
4062 } else {
4063 Log.d(TAG, "New package installed in " + destPackageFile);
4064 }
4065 }
4066 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4067 if (mInstaller != null) {
4068 mInstaller.rmdex(tmpPackageFile.getPath());
4069 }
4070 }
4071
4072 synchronized (mPackages) {
4073 grantPermissionsLP(newPackage, true);
4074 res.name = pkgName;
4075 res.uid = newPackage.applicationInfo.uid;
4076 res.pkg = newPackage;
4077 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004078 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4080 //to update install status
4081 mSettings.writeLP();
4082 }
4083 }
4084
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004085 private File getFwdLockedResource(String pkgName) {
4086 final String publicZipFileName = pkgName + ".zip";
4087 return new File(mAppInstallDir, publicZipFileName);
4088 }
4089
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004090 private File copyTempInstallFile(Uri pPackageURI,
4091 PackageInstalledInfo res) {
4092 File tmpPackageFile = createTempPackageFile();
4093 int retCode = PackageManager.INSTALL_SUCCEEDED;
4094 if (tmpPackageFile == null) {
4095 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4096 return null;
4097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004099 if (pPackageURI.getScheme().equals("file")) {
4100 final File srcPackageFile = new File(pPackageURI.getPath());
4101 // We copy the source package file to a temp file and then rename it to the
4102 // destination file in order to eliminate a window where the package directory
4103 // scanner notices the new package file but it's not completely copied yet.
4104 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4105 Log.e(TAG, "Couldn't copy package file to temp file.");
4106 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004108 } else if (pPackageURI.getScheme().equals("content")) {
4109 ParcelFileDescriptor fd = null;
4110 try {
4111 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4112 } catch (FileNotFoundException e) {
4113 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4114 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4115 }
4116 if (fd == null) {
4117 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4118 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4119 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 if (Config.LOGV) {
4121 Log.v(TAG, "Opened file descriptor from download service.");
4122 }
4123 ParcelFileDescriptor.AutoCloseInputStream
4124 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4125 // We copy the source package file to a temp file and then rename it to the
4126 // destination file in order to eliminate a window where the package directory
4127 // scanner notices the new package file but it's not completely copied yet.
4128 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4129 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004130 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004133 } else {
4134 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4135 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4136 }
4137
4138 res.returnCode = retCode;
4139 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4140 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4141 tmpPackageFile.delete();
4142 }
4143 return null;
4144 }
4145 return tmpPackageFile;
4146 }
4147
4148 private void installPackageLI(Uri pPackageURI,
4149 int pFlags, boolean newInstall, String installerPackageName,
4150 File tmpPackageFile, PackageInstalledInfo res) {
4151 String pkgName = null;
4152 boolean forwardLocked = false;
4153 boolean replacingExistingPackage = false;
4154 // Result object to be returned
4155 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4156
4157 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 pkgName = PackageParser.parsePackageName(
4159 tmpPackageFile.getAbsolutePath(), 0);
4160 if (pkgName == null) {
4161 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4162 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4163 break main_flow;
4164 }
4165 res.name = pkgName;
4166 //initialize some variables before installing pkg
4167 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004168 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 ? mDrmAppPrivateInstallDir
4170 : mAppInstallDir;
4171 final File destPackageFile = new File(destDir, pkgFileName);
4172 final String destFilePath = destPackageFile.getAbsolutePath();
4173 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004174 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004175 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 forwardLocked = true;
4177 } else {
4178 destResourceFile = destPackageFile;
4179 }
4180 // Retrieve PackageSettings and parse package
4181 int parseFlags = PackageParser.PARSE_CHATTY;
4182 parseFlags |= mDefParseFlags;
4183 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4184 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4186 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4187 if (pkg == null) {
4188 res.returnCode = pp.getParseError();
4189 break main_flow;
4190 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004191 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4192 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4193 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4194 break main_flow;
4195 }
4196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4198 res.returnCode = pp.getParseError();
4199 break main_flow;
4200 }
4201
4202 synchronized (mPackages) {
4203 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004204 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 && mPackages.containsKey(pkgName)) {
4206 replacingExistingPackage = true;
4207 }
4208 }
4209
4210 if(replacingExistingPackage) {
4211 replacePackageLI(pkgName,
4212 tmpPackageFile,
4213 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004214 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004215 res);
4216 } else {
4217 installNewPackageLI(pkgName,
4218 tmpPackageFile,
4219 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004220 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 res);
4222 }
4223 } finally {
4224 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4225 tmpPackageFile.delete();
4226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 }
4228 }
4229
4230 private int setPermissionsLI(String pkgName,
4231 PackageParser.Package newPackage,
4232 String destFilePath,
4233 File destResourceFile,
4234 boolean forwardLocked) {
4235 int retCode;
4236 if (forwardLocked) {
4237 try {
4238 extractPublicFiles(newPackage, destResourceFile);
4239 } catch (IOException e) {
4240 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4241 " forward-locked app.");
4242 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4243 } finally {
4244 //TODO clean up the extracted public files
4245 }
4246 if (mInstaller != null) {
4247 retCode = mInstaller.setForwardLockPerm(pkgName,
4248 newPackage.applicationInfo.uid);
4249 } else {
4250 final int filePermissions =
4251 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4252 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4253 newPackage.applicationInfo.uid);
4254 }
4255 } else {
4256 final int filePermissions =
4257 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4258 |FileUtils.S_IROTH;
4259 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4260 }
4261 if (retCode != 0) {
4262 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4263 + ". The return code was: " + retCode);
4264 }
4265 return PackageManager.INSTALL_SUCCEEDED;
4266 }
4267
4268 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4269 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4270 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4271 }
4272
4273 private void extractPublicFiles(PackageParser.Package newPackage,
4274 File publicZipFile) throws IOException {
4275 final ZipOutputStream publicZipOutStream =
4276 new ZipOutputStream(new FileOutputStream(publicZipFile));
4277 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4278
4279 // Copy manifest, resources.arsc and res directory to public zip
4280
4281 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4282 while (privateZipEntries.hasMoreElements()) {
4283 final ZipEntry zipEntry = privateZipEntries.nextElement();
4284 final String zipEntryName = zipEntry.getName();
4285 if ("AndroidManifest.xml".equals(zipEntryName)
4286 || "resources.arsc".equals(zipEntryName)
4287 || zipEntryName.startsWith("res/")) {
4288 try {
4289 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4290 } catch (IOException e) {
4291 try {
4292 publicZipOutStream.close();
4293 throw e;
4294 } finally {
4295 publicZipFile.delete();
4296 }
4297 }
4298 }
4299 }
4300
4301 publicZipOutStream.close();
4302 FileUtils.setPermissions(
4303 publicZipFile.getAbsolutePath(),
4304 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4305 -1, -1);
4306 }
4307
4308 private static void copyZipEntry(ZipEntry zipEntry,
4309 ZipFile inZipFile,
4310 ZipOutputStream outZipStream) throws IOException {
4311 byte[] buffer = new byte[4096];
4312 int num;
4313
4314 ZipEntry newEntry;
4315 if (zipEntry.getMethod() == ZipEntry.STORED) {
4316 // Preserve the STORED method of the input entry.
4317 newEntry = new ZipEntry(zipEntry);
4318 } else {
4319 // Create a new entry so that the compressed len is recomputed.
4320 newEntry = new ZipEntry(zipEntry.getName());
4321 }
4322 outZipStream.putNextEntry(newEntry);
4323
4324 InputStream data = inZipFile.getInputStream(zipEntry);
4325 while ((num = data.read(buffer)) > 0) {
4326 outZipStream.write(buffer, 0, num);
4327 }
4328 outZipStream.flush();
4329 }
4330
4331 private void deleteTempPackageFiles() {
4332 FilenameFilter filter = new FilenameFilter() {
4333 public boolean accept(File dir, String name) {
4334 return name.startsWith("vmdl") && name.endsWith(".tmp");
4335 }
4336 };
4337 String tmpFilesList[] = mAppInstallDir.list(filter);
4338 if(tmpFilesList == null) {
4339 return;
4340 }
4341 for(int i = 0; i < tmpFilesList.length; i++) {
4342 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4343 tmpFile.delete();
4344 }
4345 }
4346
4347 private File createTempPackageFile() {
4348 File tmpPackageFile;
4349 try {
4350 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4351 } catch (IOException e) {
4352 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4353 return null;
4354 }
4355 try {
4356 FileUtils.setPermissions(
4357 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4358 -1, -1);
4359 } catch (IOException e) {
4360 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4361 return null;
4362 }
4363 return tmpPackageFile;
4364 }
4365
4366 public void deletePackage(final String packageName,
4367 final IPackageDeleteObserver observer,
4368 final int flags) {
4369 mContext.enforceCallingOrSelfPermission(
4370 android.Manifest.permission.DELETE_PACKAGES, null);
4371 // Queue up an async operation since the package deletion may take a little while.
4372 mHandler.post(new Runnable() {
4373 public void run() {
4374 mHandler.removeCallbacks(this);
4375 final boolean succeded = deletePackageX(packageName, true, true, flags);
4376 if (observer != null) {
4377 try {
4378 observer.packageDeleted(succeded);
4379 } catch (RemoteException e) {
4380 Log.i(TAG, "Observer no longer exists.");
4381 } //end catch
4382 } //end if
4383 } //end run
4384 });
4385 }
4386
4387 /**
4388 * This method is an internal method that could be get invoked either
4389 * to delete an installed package or to clean up a failed installation.
4390 * After deleting an installed package, a broadcast is sent to notify any
4391 * listeners that the package has been installed. For cleaning up a failed
4392 * installation, the broadcast is not necessary since the package's
4393 * installation wouldn't have sent the initial broadcast either
4394 * The key steps in deleting a package are
4395 * deleting the package information in internal structures like mPackages,
4396 * deleting the packages base directories through installd
4397 * updating mSettings to reflect current status
4398 * persisting settings for later use
4399 * sending a broadcast if necessary
4400 */
4401
4402 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4403 boolean deleteCodeAndResources, int flags) {
4404 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004405 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406
4407 synchronized (mInstallLock) {
4408 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4409 }
4410
4411 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004412 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4413 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4414
4415 // If the removed package was a system update, the old system packaged
4416 // was re-enabled; we need to broadcast this information
4417 if (systemUpdate) {
4418 Bundle extras = new Bundle(1);
4419 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4420 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4421
4422 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4423 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 }
4426 return res;
4427 }
4428
4429 static class PackageRemovedInfo {
4430 String removedPackage;
4431 int uid = -1;
4432 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004433 boolean isRemovedPackageSystemUpdate = false;
4434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 void sendBroadcast(boolean fullRemove, boolean replacing) {
4436 Bundle extras = new Bundle(1);
4437 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4438 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4439 if (replacing) {
4440 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4441 }
4442 if (removedPackage != null) {
4443 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4444 }
4445 if (removedUid >= 0) {
4446 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4447 }
4448 }
4449 }
4450
4451 /*
4452 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4453 * flag is not set, the data directory is removed as well.
4454 * make sure this flag is set for partially installed apps. If not its meaningless to
4455 * delete a partially installed application.
4456 */
4457 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4458 int flags) {
4459 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004460 if (outInfo != null) {
4461 outInfo.removedPackage = packageName;
4462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 removePackageLI(p, true);
4464 // Retrieve object to delete permissions for shared user later on
4465 PackageSetting deletedPs;
4466 synchronized (mPackages) {
4467 deletedPs = mSettings.mPackages.get(packageName);
4468 }
4469 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4470 if (mInstaller != null) {
4471 int retCode = mInstaller.remove(packageName);
4472 if (retCode < 0) {
4473 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4474 + packageName + ", retcode=" + retCode);
4475 // we don't consider this to be a failure of the core package deletion
4476 }
4477 } else {
4478 //for emulator
4479 PackageParser.Package pkg = mPackages.get(packageName);
4480 File dataDir = new File(pkg.applicationInfo.dataDir);
4481 dataDir.delete();
4482 }
4483 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004484 if (outInfo != null) {
4485 outInfo.removedUid = mSettings.removePackageLP(packageName);
4486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487 }
4488 }
4489 synchronized (mPackages) {
4490 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4491 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004492 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 }
4494 // Save settings now
4495 mSettings.writeLP ();
4496 }
4497 }
4498
4499 /*
4500 * Tries to delete system package.
4501 */
4502 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004503 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 ApplicationInfo applicationInfo = p.applicationInfo;
4505 //applicable for non-partially installed applications only
4506 if (applicationInfo == null) {
4507 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4508 return false;
4509 }
4510 PackageSetting ps = null;
4511 // Confirm if the system package has been updated
4512 // An updated system app can be deleted. This will also have to restore
4513 // the system pkg from system partition
4514 synchronized (mPackages) {
4515 ps = mSettings.getDisabledSystemPkg(p.packageName);
4516 }
4517 if (ps == null) {
4518 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4519 return false;
4520 } else {
4521 Log.i(TAG, "Deleting system pkg from data partition");
4522 }
4523 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004524 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004525 boolean deleteCodeAndResources = false;
4526 if (ps.versionCode < p.mVersionCode) {
4527 // Delete code and resources for downgrades
4528 deleteCodeAndResources = true;
4529 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4530 flags &= ~PackageManager.DONT_DELETE_DATA;
4531 }
4532 } else {
4533 // Preserve data by setting flag
4534 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4535 flags |= PackageManager.DONT_DELETE_DATA;
4536 }
4537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4539 if (!ret) {
4540 return false;
4541 }
4542 synchronized (mPackages) {
4543 // Reinstate the old system package
4544 mSettings.enableSystemPackageLP(p.packageName);
4545 }
4546 // Install the system package
4547 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4548 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4549 SCAN_MONITOR);
4550
4551 if (newPkg == null) {
4552 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4553 return false;
4554 }
4555 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004556 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004557 mSettings.writeLP();
4558 }
4559 return true;
4560 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004561
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004562 private void deletePackageResourcesLI(String packageName,
4563 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004564 if (sourceDir != null) {
4565 File sourceFile = new File(sourceDir);
4566 if (!sourceFile.exists()) {
4567 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4568 }
4569 // Delete application's code and resources
4570 sourceFile.delete();
4571 if (mInstaller != null) {
4572 int retCode = mInstaller.rmdex(sourceFile.toString());
4573 if (retCode < 0) {
4574 Log.w(TAG, "Couldn't remove dex file for package: "
4575 + packageName + " at location "
4576 + sourceFile.toString() + ", retcode=" + retCode);
4577 // we don't consider this to be a failure of the core package deletion
4578 }
4579 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004580 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004581 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4582 final File publicSourceFile = new File(publicSourceDir);
4583 if (!publicSourceFile.exists()) {
4584 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4585 }
4586 if (publicSourceFile.exists()) {
4587 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004588 }
4589 }
4590 }
4591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4593 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4594 ApplicationInfo applicationInfo = p.applicationInfo;
4595 if (applicationInfo == null) {
4596 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4597 return false;
4598 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004599 if (outInfo != null) {
4600 outInfo.uid = applicationInfo.uid;
4601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602
4603 // Delete package data from internal structures and also remove data if flag is set
4604 removePackageDataLI(p, outInfo, flags);
4605
4606 // Delete application code and resources
4607 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004608 deletePackageResourcesLI(applicationInfo.packageName,
4609 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 }
4611 return true;
4612 }
4613
4614 /*
4615 * This method handles package deletion in general
4616 */
4617 private boolean deletePackageLI(String packageName,
4618 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4619 if (packageName == null) {
4620 Log.w(TAG, "Attempt to delete null packageName.");
4621 return false;
4622 }
4623 PackageParser.Package p;
4624 boolean dataOnly = false;
4625 synchronized (mPackages) {
4626 p = mPackages.get(packageName);
4627 if (p == null) {
4628 //this retrieves partially installed apps
4629 dataOnly = true;
4630 PackageSetting ps = mSettings.mPackages.get(packageName);
4631 if (ps == null) {
4632 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4633 return false;
4634 }
4635 p = ps.pkg;
4636 }
4637 }
4638 if (p == null) {
4639 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4640 return false;
4641 }
4642
4643 if (dataOnly) {
4644 // Delete application data first
4645 removePackageDataLI(p, outInfo, flags);
4646 return true;
4647 }
4648 // At this point the package should have ApplicationInfo associated with it
4649 if (p.applicationInfo == null) {
4650 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4651 return false;
4652 }
4653 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4654 Log.i(TAG, "Removing system package:"+p.packageName);
4655 // When an updated system application is deleted we delete the existing resources as well and
4656 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004657 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 }
4659 Log.i(TAG, "Removing non-system package:"+p.packageName);
4660 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4661 }
4662
4663 public void clearApplicationUserData(final String packageName,
4664 final IPackageDataObserver observer) {
4665 mContext.enforceCallingOrSelfPermission(
4666 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4667 // Queue up an async operation since the package deletion may take a little while.
4668 mHandler.post(new Runnable() {
4669 public void run() {
4670 mHandler.removeCallbacks(this);
4671 final boolean succeeded;
4672 synchronized (mInstallLock) {
4673 succeeded = clearApplicationUserDataLI(packageName);
4674 }
4675 if (succeeded) {
4676 // invoke DeviceStorageMonitor's update method to clear any notifications
4677 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4678 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4679 if (dsm != null) {
4680 dsm.updateMemory();
4681 }
4682 }
4683 if(observer != null) {
4684 try {
4685 observer.onRemoveCompleted(packageName, succeeded);
4686 } catch (RemoteException e) {
4687 Log.i(TAG, "Observer no longer exists.");
4688 }
4689 } //end if observer
4690 } //end run
4691 });
4692 }
4693
4694 private boolean clearApplicationUserDataLI(String packageName) {
4695 if (packageName == null) {
4696 Log.w(TAG, "Attempt to delete null packageName.");
4697 return false;
4698 }
4699 PackageParser.Package p;
4700 boolean dataOnly = false;
4701 synchronized (mPackages) {
4702 p = mPackages.get(packageName);
4703 if(p == null) {
4704 dataOnly = true;
4705 PackageSetting ps = mSettings.mPackages.get(packageName);
4706 if((ps == null) || (ps.pkg == null)) {
4707 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4708 return false;
4709 }
4710 p = ps.pkg;
4711 }
4712 }
4713 if(!dataOnly) {
4714 //need to check this only for fully installed applications
4715 if (p == null) {
4716 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4717 return false;
4718 }
4719 final ApplicationInfo applicationInfo = p.applicationInfo;
4720 if (applicationInfo == null) {
4721 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4722 return false;
4723 }
4724 }
4725 if (mInstaller != null) {
4726 int retCode = mInstaller.clearUserData(packageName);
4727 if (retCode < 0) {
4728 Log.w(TAG, "Couldn't remove cache files for package: "
4729 + packageName);
4730 return false;
4731 }
4732 }
4733 return true;
4734 }
4735
4736 public void deleteApplicationCacheFiles(final String packageName,
4737 final IPackageDataObserver observer) {
4738 mContext.enforceCallingOrSelfPermission(
4739 android.Manifest.permission.DELETE_CACHE_FILES, null);
4740 // Queue up an async operation since the package deletion may take a little while.
4741 mHandler.post(new Runnable() {
4742 public void run() {
4743 mHandler.removeCallbacks(this);
4744 final boolean succeded;
4745 synchronized (mInstallLock) {
4746 succeded = deleteApplicationCacheFilesLI(packageName);
4747 }
4748 if(observer != null) {
4749 try {
4750 observer.onRemoveCompleted(packageName, succeded);
4751 } catch (RemoteException e) {
4752 Log.i(TAG, "Observer no longer exists.");
4753 }
4754 } //end if observer
4755 } //end run
4756 });
4757 }
4758
4759 private boolean deleteApplicationCacheFilesLI(String packageName) {
4760 if (packageName == null) {
4761 Log.w(TAG, "Attempt to delete null packageName.");
4762 return false;
4763 }
4764 PackageParser.Package p;
4765 synchronized (mPackages) {
4766 p = mPackages.get(packageName);
4767 }
4768 if (p == null) {
4769 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4770 return false;
4771 }
4772 final ApplicationInfo applicationInfo = p.applicationInfo;
4773 if (applicationInfo == null) {
4774 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4775 return false;
4776 }
4777 if (mInstaller != null) {
4778 int retCode = mInstaller.deleteCacheFiles(packageName);
4779 if (retCode < 0) {
4780 Log.w(TAG, "Couldn't remove cache files for package: "
4781 + packageName);
4782 return false;
4783 }
4784 }
4785 return true;
4786 }
4787
4788 public void getPackageSizeInfo(final String packageName,
4789 final IPackageStatsObserver observer) {
4790 mContext.enforceCallingOrSelfPermission(
4791 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4792 // Queue up an async operation since the package deletion may take a little while.
4793 mHandler.post(new Runnable() {
4794 public void run() {
4795 mHandler.removeCallbacks(this);
4796 PackageStats lStats = new PackageStats(packageName);
4797 final boolean succeded;
4798 synchronized (mInstallLock) {
4799 succeded = getPackageSizeInfoLI(packageName, lStats);
4800 }
4801 if(observer != null) {
4802 try {
4803 observer.onGetStatsCompleted(lStats, succeded);
4804 } catch (RemoteException e) {
4805 Log.i(TAG, "Observer no longer exists.");
4806 }
4807 } //end if observer
4808 } //end run
4809 });
4810 }
4811
4812 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4813 if (packageName == null) {
4814 Log.w(TAG, "Attempt to get size of null packageName.");
4815 return false;
4816 }
4817 PackageParser.Package p;
4818 boolean dataOnly = false;
4819 synchronized (mPackages) {
4820 p = mPackages.get(packageName);
4821 if(p == null) {
4822 dataOnly = true;
4823 PackageSetting ps = mSettings.mPackages.get(packageName);
4824 if((ps == null) || (ps.pkg == null)) {
4825 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4826 return false;
4827 }
4828 p = ps.pkg;
4829 }
4830 }
4831 String publicSrcDir = null;
4832 if(!dataOnly) {
4833 final ApplicationInfo applicationInfo = p.applicationInfo;
4834 if (applicationInfo == null) {
4835 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4836 return false;
4837 }
4838 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4839 }
4840 if (mInstaller != null) {
4841 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4842 publicSrcDir, pStats);
4843 if (res < 0) {
4844 return false;
4845 } else {
4846 return true;
4847 }
4848 }
4849 return true;
4850 }
4851
4852
4853 public void addPackageToPreferred(String packageName) {
4854 mContext.enforceCallingOrSelfPermission(
4855 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4856
4857 synchronized (mPackages) {
4858 PackageParser.Package p = mPackages.get(packageName);
4859 if (p == null) {
4860 return;
4861 }
4862 PackageSetting ps = (PackageSetting)p.mExtras;
4863 if (ps != null) {
4864 mSettings.mPreferredPackages.remove(ps);
4865 mSettings.mPreferredPackages.add(0, ps);
4866 updatePreferredIndicesLP();
4867 mSettings.writeLP();
4868 }
4869 }
4870 }
4871
4872 public void removePackageFromPreferred(String packageName) {
4873 mContext.enforceCallingOrSelfPermission(
4874 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4875
4876 synchronized (mPackages) {
4877 PackageParser.Package p = mPackages.get(packageName);
4878 if (p == null) {
4879 return;
4880 }
4881 if (p.mPreferredOrder > 0) {
4882 PackageSetting ps = (PackageSetting)p.mExtras;
4883 if (ps != null) {
4884 mSettings.mPreferredPackages.remove(ps);
4885 p.mPreferredOrder = 0;
4886 updatePreferredIndicesLP();
4887 mSettings.writeLP();
4888 }
4889 }
4890 }
4891 }
4892
4893 private void updatePreferredIndicesLP() {
4894 final ArrayList<PackageSetting> pkgs
4895 = mSettings.mPreferredPackages;
4896 final int N = pkgs.size();
4897 for (int i=0; i<N; i++) {
4898 pkgs.get(i).pkg.mPreferredOrder = N - i;
4899 }
4900 }
4901
4902 public List<PackageInfo> getPreferredPackages(int flags) {
4903 synchronized (mPackages) {
4904 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4905 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4906 final int N = pref.size();
4907 for (int i=0; i<N; i++) {
4908 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4909 }
4910 return res;
4911 }
4912 }
4913
4914 public void addPreferredActivity(IntentFilter filter, int match,
4915 ComponentName[] set, ComponentName activity) {
4916 mContext.enforceCallingOrSelfPermission(
4917 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4918
4919 synchronized (mPackages) {
4920 Log.i(TAG, "Adding preferred activity " + activity + ":");
4921 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4922 mSettings.mPreferredActivities.addFilter(
4923 new PreferredActivity(filter, match, set, activity));
4924 mSettings.writeLP();
4925 }
4926 }
4927
Satish Sampath8dbe6122009-06-02 23:35:54 +01004928 public void replacePreferredActivity(IntentFilter filter, int match,
4929 ComponentName[] set, ComponentName activity) {
4930 mContext.enforceCallingOrSelfPermission(
4931 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4932 if (filter.countActions() != 1) {
4933 throw new IllegalArgumentException(
4934 "replacePreferredActivity expects filter to have only 1 action.");
4935 }
4936 if (filter.countCategories() != 1) {
4937 throw new IllegalArgumentException(
4938 "replacePreferredActivity expects filter to have only 1 category.");
4939 }
4940 if (filter.countDataAuthorities() != 0
4941 || filter.countDataPaths() != 0
4942 || filter.countDataSchemes() != 0
4943 || filter.countDataTypes() != 0) {
4944 throw new IllegalArgumentException(
4945 "replacePreferredActivity expects filter to have no data authorities, " +
4946 "paths, schemes or types.");
4947 }
4948 synchronized (mPackages) {
4949 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4950 String action = filter.getAction(0);
4951 String category = filter.getCategory(0);
4952 while (it.hasNext()) {
4953 PreferredActivity pa = it.next();
4954 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
4955 it.remove();
4956 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
4957 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4958 }
4959 }
4960 addPreferredActivity(filter, match, set, activity);
4961 }
4962 }
4963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 public void clearPackagePreferredActivities(String packageName) {
4965 mContext.enforceCallingOrSelfPermission(
4966 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4967
4968 synchronized (mPackages) {
4969 if (clearPackagePreferredActivitiesLP(packageName)) {
4970 mSettings.writeLP();
4971 }
4972 }
4973 }
4974
4975 boolean clearPackagePreferredActivitiesLP(String packageName) {
4976 boolean changed = false;
4977 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4978 while (it.hasNext()) {
4979 PreferredActivity pa = it.next();
4980 if (pa.mActivity.getPackageName().equals(packageName)) {
4981 it.remove();
4982 changed = true;
4983 }
4984 }
4985 return changed;
4986 }
4987
4988 public int getPreferredActivities(List<IntentFilter> outFilters,
4989 List<ComponentName> outActivities, String packageName) {
4990
4991 int num = 0;
4992 synchronized (mPackages) {
4993 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4994 while (it.hasNext()) {
4995 PreferredActivity pa = it.next();
4996 if (packageName == null
4997 || pa.mActivity.getPackageName().equals(packageName)) {
4998 if (outFilters != null) {
4999 outFilters.add(new IntentFilter(pa));
5000 }
5001 if (outActivities != null) {
5002 outActivities.add(pa.mActivity);
5003 }
5004 }
5005 }
5006 }
5007
5008 return num;
5009 }
5010
5011 public void setApplicationEnabledSetting(String appPackageName,
5012 int newState, int flags) {
5013 setEnabledSetting(appPackageName, null, newState, flags);
5014 }
5015
5016 public void setComponentEnabledSetting(ComponentName componentName,
5017 int newState, int flags) {
5018 setEnabledSetting(componentName.getPackageName(),
5019 componentName.getClassName(), newState, flags);
5020 }
5021
5022 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005023 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5025 || newState == COMPONENT_ENABLED_STATE_ENABLED
5026 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5027 throw new IllegalArgumentException("Invalid new component state: "
5028 + newState);
5029 }
5030 PackageSetting pkgSetting;
5031 final int uid = Binder.getCallingUid();
5032 final int permission = mContext.checkCallingPermission(
5033 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5034 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005035 boolean sendNow = false;
5036 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005037 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005039 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005041 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005043 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005045 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 }
5047 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005048 "Unknown component: " + packageName
5049 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005050 }
5051 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5052 throw new SecurityException(
5053 "Permission Denial: attempt to change component state from pid="
5054 + Binder.getCallingPid()
5055 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5056 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005057 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 // We're dealing with an application/package level state change
5059 pkgSetting.enabled = newState;
5060 } else {
5061 // We're dealing with a component level state change
5062 switch (newState) {
5063 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005064 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 break;
5066 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005067 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 break;
5069 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005070 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 break;
5072 default:
5073 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005074 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 }
5076 }
5077 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005078 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005079 components = mPendingBroadcasts.get(packageName);
5080 boolean newPackage = components == null;
5081 if (newPackage) {
5082 components = new ArrayList<String>();
5083 }
5084 if (!components.contains(componentName)) {
5085 components.add(componentName);
5086 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005087 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5088 sendNow = true;
5089 // Purge entry from pending broadcast list if another one exists already
5090 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005091 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005092 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005093 if (newPackage) {
5094 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005095 }
5096 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5097 // Schedule a message
5098 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5099 }
5100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005101 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 long callingId = Binder.clearCallingIdentity();
5104 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005105 if (sendNow) {
5106 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005107 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 } finally {
5110 Binder.restoreCallingIdentity(callingId);
5111 }
5112 }
5113
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005114 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005115 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5116 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5117 + " components=" + componentNames);
5118 Bundle extras = new Bundle(4);
5119 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5120 String nameList[] = new String[componentNames.size()];
5121 componentNames.toArray(nameList);
5122 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005123 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5124 extras.putInt(Intent.EXTRA_UID, packageUid);
5125 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
5126 }
5127
Jacek Surazski65e13172009-04-28 15:26:38 +02005128 public String getInstallerPackageName(String packageName) {
5129 synchronized (mPackages) {
5130 PackageSetting pkg = mSettings.mPackages.get(packageName);
5131 if (pkg == null) {
5132 throw new IllegalArgumentException("Unknown package: " + packageName);
5133 }
5134 return pkg.installerPackageName;
5135 }
5136 }
5137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 public int getApplicationEnabledSetting(String appPackageName) {
5139 synchronized (mPackages) {
5140 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5141 if (pkg == null) {
5142 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5143 }
5144 return pkg.enabled;
5145 }
5146 }
5147
5148 public int getComponentEnabledSetting(ComponentName componentName) {
5149 synchronized (mPackages) {
5150 final String packageNameStr = componentName.getPackageName();
5151 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5152 if (pkg == null) {
5153 throw new IllegalArgumentException("Unknown component: " + componentName);
5154 }
5155 final String classNameStr = componentName.getClassName();
5156 return pkg.currentEnabledStateLP(classNameStr);
5157 }
5158 }
5159
5160 public void enterSafeMode() {
5161 if (!mSystemReady) {
5162 mSafeMode = true;
5163 }
5164 }
5165
5166 public void systemReady() {
5167 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005168
5169 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005170 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005171 mContext.getContentResolver(),
5172 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005173 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005174 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005175 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 }
5178
5179 public boolean isSafeMode() {
5180 return mSafeMode;
5181 }
5182
5183 public boolean hasSystemUidErrors() {
5184 return mHasSystemUidErrors;
5185 }
5186
5187 static String arrayToString(int[] array) {
5188 StringBuffer buf = new StringBuffer(128);
5189 buf.append('[');
5190 if (array != null) {
5191 for (int i=0; i<array.length; i++) {
5192 if (i > 0) buf.append(", ");
5193 buf.append(array[i]);
5194 }
5195 }
5196 buf.append(']');
5197 return buf.toString();
5198 }
5199
5200 @Override
5201 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5202 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5203 != PackageManager.PERMISSION_GRANTED) {
5204 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5205 + Binder.getCallingPid()
5206 + ", uid=" + Binder.getCallingUid()
5207 + " without permission "
5208 + android.Manifest.permission.DUMP);
5209 return;
5210 }
5211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 synchronized (mPackages) {
5213 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005214 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005215 pw.println(" ");
5216 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005217 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 pw.println(" ");
5219 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005220 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 pw.println(" ");
5222 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005223 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 pw.println(" ");
5225 pw.println("Preferred Packages:");
5226 {
5227 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005228 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 }
5230 }
5231 pw.println(" ");
5232 pw.println("Permissions:");
5233 {
5234 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005235 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5236 pw.print(Integer.toHexString(System.identityHashCode(p)));
5237 pw.println("):");
5238 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5239 pw.print(" uid="); pw.print(p.uid);
5240 pw.print(" gids="); pw.print(arrayToString(p.gids));
5241 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 }
5243 }
5244 pw.println(" ");
5245 pw.println("Packages:");
5246 {
5247 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005248 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5249 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5250 pw.println("):");
5251 pw.print(" userId="); pw.print(ps.userId);
5252 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5253 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5254 pw.print(" pkg="); pw.println(ps.pkg);
5255 pw.print(" codePath="); pw.println(ps.codePathString);
5256 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005258 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005259 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005260 pw.print(" supportsScreens=[");
5261 boolean first = true;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005262 if ((ps.pkg.applicationInfo.flags &
5263 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005264 if (!first) pw.print(", ");
5265 first = false;
5266 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005267 }
5268 if ((ps.pkg.applicationInfo.flags &
5269 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005270 if (!first) pw.print(", ");
5271 first = false;
5272 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005273 }
5274 if ((ps.pkg.applicationInfo.flags &
5275 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005276 if (!first) pw.print(", ");
5277 first = false;
5278 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005279 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005280 if ((ps.pkg.applicationInfo.flags &
5281 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005282 if (!first) pw.print(", ");
5283 first = false;
5284 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005285 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005286 if ((ps.pkg.applicationInfo.flags &
5287 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5288 if (!first) pw.print(", ");
5289 first = false;
5290 pw.print("anyDensity");
5291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005293 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005294 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5295 pw.print(" signatures="); pw.println(ps.signatures);
5296 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5297 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5298 pw.print(" installStatus="); pw.print(ps.installStatus);
5299 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 if (ps.disabledComponents.size() > 0) {
5301 pw.println(" disabledComponents:");
5302 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005303 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 }
5305 }
5306 if (ps.enabledComponents.size() > 0) {
5307 pw.println(" enabledComponents:");
5308 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005309 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 }
5311 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005312 if (ps.grantedPermissions.size() > 0) {
5313 pw.println(" grantedPermissions:");
5314 for (String s : ps.grantedPermissions) {
5315 pw.print(" "); pw.println(s);
5316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005318 if (ps.loadedPermissions.size() > 0) {
5319 pw.println(" loadedPermissions:");
5320 for (String s : ps.loadedPermissions) {
5321 pw.print(" "); pw.println(s);
5322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 }
5324 }
5325 }
5326 pw.println(" ");
5327 pw.println("Shared Users:");
5328 {
5329 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005330 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5331 pw.print(Integer.toHexString(System.identityHashCode(su)));
5332 pw.println("):");
5333 pw.print(" userId="); pw.print(su.userId);
5334 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 pw.println(" grantedPermissions:");
5336 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005337 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 }
5339 pw.println(" loadedPermissions:");
5340 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005341 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
5343 }
5344 }
5345 pw.println(" ");
5346 pw.println("Settings parse messages:");
5347 pw.println(mSettings.mReadMessages.toString());
5348 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005349
5350 synchronized (mProviders) {
5351 pw.println(" ");
5352 pw.println("Registered ContentProviders:");
5353 for (PackageParser.Provider p : mProviders.values()) {
5354 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5355 pw.println(p.toString());
5356 }
5357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 }
5359
5360 static final class BasePermission {
5361 final static int TYPE_NORMAL = 0;
5362 final static int TYPE_BUILTIN = 1;
5363 final static int TYPE_DYNAMIC = 2;
5364
5365 final String name;
5366 final String sourcePackage;
5367 final int type;
5368 PackageParser.Permission perm;
5369 PermissionInfo pendingInfo;
5370 int uid;
5371 int[] gids;
5372
5373 BasePermission(String _name, String _sourcePackage, int _type) {
5374 name = _name;
5375 sourcePackage = _sourcePackage;
5376 type = _type;
5377 }
5378 }
5379
5380 static class PackageSignatures {
5381 private Signature[] mSignatures;
5382
5383 PackageSignatures(Signature[] sigs) {
5384 assignSignatures(sigs);
5385 }
5386
5387 PackageSignatures() {
5388 }
5389
5390 void writeXml(XmlSerializer serializer, String tagName,
5391 ArrayList<Signature> pastSignatures) throws IOException {
5392 if (mSignatures == null) {
5393 return;
5394 }
5395 serializer.startTag(null, tagName);
5396 serializer.attribute(null, "count",
5397 Integer.toString(mSignatures.length));
5398 for (int i=0; i<mSignatures.length; i++) {
5399 serializer.startTag(null, "cert");
5400 final Signature sig = mSignatures[i];
5401 final int sigHash = sig.hashCode();
5402 final int numPast = pastSignatures.size();
5403 int j;
5404 for (j=0; j<numPast; j++) {
5405 Signature pastSig = pastSignatures.get(j);
5406 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5407 serializer.attribute(null, "index", Integer.toString(j));
5408 break;
5409 }
5410 }
5411 if (j >= numPast) {
5412 pastSignatures.add(sig);
5413 serializer.attribute(null, "index", Integer.toString(numPast));
5414 serializer.attribute(null, "key", sig.toCharsString());
5415 }
5416 serializer.endTag(null, "cert");
5417 }
5418 serializer.endTag(null, tagName);
5419 }
5420
5421 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5422 throws IOException, XmlPullParserException {
5423 String countStr = parser.getAttributeValue(null, "count");
5424 if (countStr == null) {
5425 reportSettingsProblem(Log.WARN,
5426 "Error in package manager settings: <signatures> has"
5427 + " no count at " + parser.getPositionDescription());
5428 XmlUtils.skipCurrentTag(parser);
5429 }
5430 final int count = Integer.parseInt(countStr);
5431 mSignatures = new Signature[count];
5432 int pos = 0;
5433
5434 int outerDepth = parser.getDepth();
5435 int type;
5436 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5437 && (type != XmlPullParser.END_TAG
5438 || parser.getDepth() > outerDepth)) {
5439 if (type == XmlPullParser.END_TAG
5440 || type == XmlPullParser.TEXT) {
5441 continue;
5442 }
5443
5444 String tagName = parser.getName();
5445 if (tagName.equals("cert")) {
5446 if (pos < count) {
5447 String index = parser.getAttributeValue(null, "index");
5448 if (index != null) {
5449 try {
5450 int idx = Integer.parseInt(index);
5451 String key = parser.getAttributeValue(null, "key");
5452 if (key == null) {
5453 if (idx >= 0 && idx < pastSignatures.size()) {
5454 Signature sig = pastSignatures.get(idx);
5455 if (sig != null) {
5456 mSignatures[pos] = pastSignatures.get(idx);
5457 pos++;
5458 } else {
5459 reportSettingsProblem(Log.WARN,
5460 "Error in package manager settings: <cert> "
5461 + "index " + index + " is not defined at "
5462 + parser.getPositionDescription());
5463 }
5464 } else {
5465 reportSettingsProblem(Log.WARN,
5466 "Error in package manager settings: <cert> "
5467 + "index " + index + " is out of bounds at "
5468 + parser.getPositionDescription());
5469 }
5470 } else {
5471 while (pastSignatures.size() <= idx) {
5472 pastSignatures.add(null);
5473 }
5474 Signature sig = new Signature(key);
5475 pastSignatures.set(idx, sig);
5476 mSignatures[pos] = sig;
5477 pos++;
5478 }
5479 } catch (NumberFormatException e) {
5480 reportSettingsProblem(Log.WARN,
5481 "Error in package manager settings: <cert> "
5482 + "index " + index + " is not a number at "
5483 + parser.getPositionDescription());
5484 }
5485 } else {
5486 reportSettingsProblem(Log.WARN,
5487 "Error in package manager settings: <cert> has"
5488 + " no index at " + parser.getPositionDescription());
5489 }
5490 } else {
5491 reportSettingsProblem(Log.WARN,
5492 "Error in package manager settings: too "
5493 + "many <cert> tags, expected " + count
5494 + " at " + parser.getPositionDescription());
5495 }
5496 } else {
5497 reportSettingsProblem(Log.WARN,
5498 "Unknown element under <cert>: "
5499 + parser.getName());
5500 }
5501 XmlUtils.skipCurrentTag(parser);
5502 }
5503
5504 if (pos < count) {
5505 // Should never happen -- there is an error in the written
5506 // settings -- but if it does we don't want to generate
5507 // a bad array.
5508 Signature[] newSigs = new Signature[pos];
5509 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5510 mSignatures = newSigs;
5511 }
5512 }
5513
5514 /**
5515 * If any of the given 'sigs' is contained in the existing signatures,
5516 * then completely replace the current signatures with the ones in
5517 * 'sigs'. This is used for updating an existing package to a newly
5518 * installed version.
5519 */
5520 boolean updateSignatures(Signature[] sigs, boolean update) {
5521 if (mSignatures == null) {
5522 if (update) {
5523 assignSignatures(sigs);
5524 }
5525 return true;
5526 }
5527 if (sigs == null) {
5528 return false;
5529 }
5530
5531 for (int i=0; i<sigs.length; i++) {
5532 Signature sig = sigs[i];
5533 for (int j=0; j<mSignatures.length; j++) {
5534 if (mSignatures[j].equals(sig)) {
5535 if (update) {
5536 assignSignatures(sigs);
5537 }
5538 return true;
5539 }
5540 }
5541 }
5542 return false;
5543 }
5544
5545 /**
5546 * If any of the given 'sigs' is contained in the existing signatures,
5547 * then add in any new signatures found in 'sigs'. This is used for
5548 * including a new package into an existing shared user id.
5549 */
5550 boolean mergeSignatures(Signature[] sigs, boolean update) {
5551 if (mSignatures == null) {
5552 if (update) {
5553 assignSignatures(sigs);
5554 }
5555 return true;
5556 }
5557 if (sigs == null) {
5558 return false;
5559 }
5560
5561 Signature[] added = null;
5562 int addedCount = 0;
5563 boolean haveMatch = false;
5564 for (int i=0; i<sigs.length; i++) {
5565 Signature sig = sigs[i];
5566 boolean found = false;
5567 for (int j=0; j<mSignatures.length; j++) {
5568 if (mSignatures[j].equals(sig)) {
5569 found = true;
5570 haveMatch = true;
5571 break;
5572 }
5573 }
5574
5575 if (!found) {
5576 if (added == null) {
5577 added = new Signature[sigs.length];
5578 }
5579 added[i] = sig;
5580 addedCount++;
5581 }
5582 }
5583
5584 if (!haveMatch) {
5585 // Nothing matched -- reject the new signatures.
5586 return false;
5587 }
5588 if (added == null) {
5589 // Completely matched -- nothing else to do.
5590 return true;
5591 }
5592
5593 // Add additional signatures in.
5594 if (update) {
5595 Signature[] total = new Signature[addedCount+mSignatures.length];
5596 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5597 int j = mSignatures.length;
5598 for (int i=0; i<added.length; i++) {
5599 if (added[i] != null) {
5600 total[j] = added[i];
5601 j++;
5602 }
5603 }
5604 mSignatures = total;
5605 }
5606 return true;
5607 }
5608
5609 private void assignSignatures(Signature[] sigs) {
5610 if (sigs == null) {
5611 mSignatures = null;
5612 return;
5613 }
5614 mSignatures = new Signature[sigs.length];
5615 for (int i=0; i<sigs.length; i++) {
5616 mSignatures[i] = sigs[i];
5617 }
5618 }
5619
5620 @Override
5621 public String toString() {
5622 StringBuffer buf = new StringBuffer(128);
5623 buf.append("PackageSignatures{");
5624 buf.append(Integer.toHexString(System.identityHashCode(this)));
5625 buf.append(" [");
5626 if (mSignatures != null) {
5627 for (int i=0; i<mSignatures.length; i++) {
5628 if (i > 0) buf.append(", ");
5629 buf.append(Integer.toHexString(
5630 System.identityHashCode(mSignatures[i])));
5631 }
5632 }
5633 buf.append("]}");
5634 return buf.toString();
5635 }
5636 }
5637
5638 static class PreferredActivity extends IntentFilter {
5639 final int mMatch;
5640 final String[] mSetPackages;
5641 final String[] mSetClasses;
5642 final String[] mSetComponents;
5643 final ComponentName mActivity;
5644 final String mShortActivity;
5645 String mParseError;
5646
5647 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5648 ComponentName activity) {
5649 super(filter);
5650 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5651 mActivity = activity;
5652 mShortActivity = activity.flattenToShortString();
5653 mParseError = null;
5654 if (set != null) {
5655 final int N = set.length;
5656 String[] myPackages = new String[N];
5657 String[] myClasses = new String[N];
5658 String[] myComponents = new String[N];
5659 for (int i=0; i<N; i++) {
5660 ComponentName cn = set[i];
5661 if (cn == null) {
5662 mSetPackages = null;
5663 mSetClasses = null;
5664 mSetComponents = null;
5665 return;
5666 }
5667 myPackages[i] = cn.getPackageName().intern();
5668 myClasses[i] = cn.getClassName().intern();
5669 myComponents[i] = cn.flattenToShortString().intern();
5670 }
5671 mSetPackages = myPackages;
5672 mSetClasses = myClasses;
5673 mSetComponents = myComponents;
5674 } else {
5675 mSetPackages = null;
5676 mSetClasses = null;
5677 mSetComponents = null;
5678 }
5679 }
5680
5681 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5682 IOException {
5683 mShortActivity = parser.getAttributeValue(null, "name");
5684 mActivity = ComponentName.unflattenFromString(mShortActivity);
5685 if (mActivity == null) {
5686 mParseError = "Bad activity name " + mShortActivity;
5687 }
5688 String matchStr = parser.getAttributeValue(null, "match");
5689 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5690 String setCountStr = parser.getAttributeValue(null, "set");
5691 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5692
5693 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5694 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5695 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5696
5697 int setPos = 0;
5698
5699 int outerDepth = parser.getDepth();
5700 int type;
5701 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5702 && (type != XmlPullParser.END_TAG
5703 || parser.getDepth() > outerDepth)) {
5704 if (type == XmlPullParser.END_TAG
5705 || type == XmlPullParser.TEXT) {
5706 continue;
5707 }
5708
5709 String tagName = parser.getName();
5710 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5711 // + parser.getDepth() + " tag=" + tagName);
5712 if (tagName.equals("set")) {
5713 String name = parser.getAttributeValue(null, "name");
5714 if (name == null) {
5715 if (mParseError == null) {
5716 mParseError = "No name in set tag in preferred activity "
5717 + mShortActivity;
5718 }
5719 } else if (setPos >= setCount) {
5720 if (mParseError == null) {
5721 mParseError = "Too many set tags in preferred activity "
5722 + mShortActivity;
5723 }
5724 } else {
5725 ComponentName cn = ComponentName.unflattenFromString(name);
5726 if (cn == null) {
5727 if (mParseError == null) {
5728 mParseError = "Bad set name " + name + " in preferred activity "
5729 + mShortActivity;
5730 }
5731 } else {
5732 myPackages[setPos] = cn.getPackageName();
5733 myClasses[setPos] = cn.getClassName();
5734 myComponents[setPos] = name;
5735 setPos++;
5736 }
5737 }
5738 XmlUtils.skipCurrentTag(parser);
5739 } else if (tagName.equals("filter")) {
5740 //Log.i(TAG, "Starting to parse filter...");
5741 readFromXml(parser);
5742 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5743 // + parser.getDepth() + " tag=" + parser.getName());
5744 } else {
5745 reportSettingsProblem(Log.WARN,
5746 "Unknown element under <preferred-activities>: "
5747 + parser.getName());
5748 XmlUtils.skipCurrentTag(parser);
5749 }
5750 }
5751
5752 if (setPos != setCount) {
5753 if (mParseError == null) {
5754 mParseError = "Not enough set tags (expected " + setCount
5755 + " but found " + setPos + ") in " + mShortActivity;
5756 }
5757 }
5758
5759 mSetPackages = myPackages;
5760 mSetClasses = myClasses;
5761 mSetComponents = myComponents;
5762 }
5763
5764 public void writeToXml(XmlSerializer serializer) throws IOException {
5765 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5766 serializer.attribute(null, "name", mShortActivity);
5767 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5768 serializer.attribute(null, "set", Integer.toString(NS));
5769 for (int s=0; s<NS; s++) {
5770 serializer.startTag(null, "set");
5771 serializer.attribute(null, "name", mSetComponents[s]);
5772 serializer.endTag(null, "set");
5773 }
5774 serializer.startTag(null, "filter");
5775 super.writeToXml(serializer);
5776 serializer.endTag(null, "filter");
5777 }
5778
5779 boolean sameSet(List<ResolveInfo> query, int priority) {
5780 if (mSetPackages == null) return false;
5781 final int NQ = query.size();
5782 final int NS = mSetPackages.length;
5783 int numMatch = 0;
5784 for (int i=0; i<NQ; i++) {
5785 ResolveInfo ri = query.get(i);
5786 if (ri.priority != priority) continue;
5787 ActivityInfo ai = ri.activityInfo;
5788 boolean good = false;
5789 for (int j=0; j<NS; j++) {
5790 if (mSetPackages[j].equals(ai.packageName)
5791 && mSetClasses[j].equals(ai.name)) {
5792 numMatch++;
5793 good = true;
5794 break;
5795 }
5796 }
5797 if (!good) return false;
5798 }
5799 return numMatch == NS;
5800 }
5801 }
5802
5803 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005804 int pkgFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805
5806 HashSet<String> grantedPermissions = new HashSet<String>();
5807 int[] gids;
5808
5809 HashSet<String> loadedPermissions = new HashSet<String>();
5810
5811 GrantedPermissions(int pkgFlags) {
5812 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5813 }
5814 }
5815
5816 /**
5817 * Settings base class for pending and resolved classes.
5818 */
5819 static class PackageSettingBase extends GrantedPermissions {
5820 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005821 File codePath;
5822 String codePathString;
5823 File resourcePath;
5824 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005825 private long timeStamp;
5826 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005827 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828
5829 PackageSignatures signatures = new PackageSignatures();
5830
5831 boolean permissionsFixed;
5832
5833 /* Explicitly disabled components */
5834 HashSet<String> disabledComponents = new HashSet<String>(0);
5835 /* Explicitly enabled components */
5836 HashSet<String> enabledComponents = new HashSet<String>(0);
5837 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5838 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005839
5840 /* package name of the app that installed this package */
5841 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005842
5843 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005844 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 super(pkgFlags);
5846 this.name = name;
5847 this.codePath = codePath;
5848 this.codePathString = codePath.toString();
5849 this.resourcePath = resourcePath;
5850 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005851 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 }
5853
Jacek Surazski65e13172009-04-28 15:26:38 +02005854 public void setInstallerPackageName(String packageName) {
5855 installerPackageName = packageName;
5856 }
5857
5858 String getInstallerPackageName() {
5859 return installerPackageName;
5860 }
5861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 public void setInstallStatus(int newStatus) {
5863 installStatus = newStatus;
5864 }
5865
5866 public int getInstallStatus() {
5867 return installStatus;
5868 }
5869
5870 public void setTimeStamp(long newStamp) {
5871 if (newStamp != timeStamp) {
5872 timeStamp = newStamp;
5873 timeStampString = Long.toString(newStamp);
5874 }
5875 }
5876
5877 public void setTimeStamp(long newStamp, String newStampStr) {
5878 timeStamp = newStamp;
5879 timeStampString = newStampStr;
5880 }
5881
5882 public long getTimeStamp() {
5883 return timeStamp;
5884 }
5885
5886 public String getTimeStampStr() {
5887 return timeStampString;
5888 }
5889
5890 public void copyFrom(PackageSettingBase base) {
5891 grantedPermissions = base.grantedPermissions;
5892 gids = base.gids;
5893 loadedPermissions = base.loadedPermissions;
5894
5895 timeStamp = base.timeStamp;
5896 timeStampString = base.timeStampString;
5897 signatures = base.signatures;
5898 permissionsFixed = base.permissionsFixed;
5899 disabledComponents = base.disabledComponents;
5900 enabledComponents = base.enabledComponents;
5901 enabled = base.enabled;
5902 installStatus = base.installStatus;
5903 }
5904
5905 void enableComponentLP(String componentClassName) {
5906 disabledComponents.remove(componentClassName);
5907 enabledComponents.add(componentClassName);
5908 }
5909
5910 void disableComponentLP(String componentClassName) {
5911 enabledComponents.remove(componentClassName);
5912 disabledComponents.add(componentClassName);
5913 }
5914
5915 void restoreComponentLP(String componentClassName) {
5916 enabledComponents.remove(componentClassName);
5917 disabledComponents.remove(componentClassName);
5918 }
5919
5920 int currentEnabledStateLP(String componentName) {
5921 if (enabledComponents.contains(componentName)) {
5922 return COMPONENT_ENABLED_STATE_ENABLED;
5923 } else if (disabledComponents.contains(componentName)) {
5924 return COMPONENT_ENABLED_STATE_DISABLED;
5925 } else {
5926 return COMPONENT_ENABLED_STATE_DEFAULT;
5927 }
5928 }
5929 }
5930
5931 /**
5932 * Settings data for a particular package we know about.
5933 */
5934 static final class PackageSetting extends PackageSettingBase {
5935 int userId;
5936 PackageParser.Package pkg;
5937 SharedUserSetting sharedUser;
5938
5939 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005940 int pVersionCode, int pkgFlags) {
5941 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 }
5943
5944 @Override
5945 public String toString() {
5946 return "PackageSetting{"
5947 + Integer.toHexString(System.identityHashCode(this))
5948 + " " + name + "/" + userId + "}";
5949 }
5950 }
5951
5952 /**
5953 * Settings data for a particular shared user ID we know about.
5954 */
5955 static final class SharedUserSetting extends GrantedPermissions {
5956 final String name;
5957 int userId;
5958 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5959 final PackageSignatures signatures = new PackageSignatures();
5960
5961 SharedUserSetting(String _name, int _pkgFlags) {
5962 super(_pkgFlags);
5963 name = _name;
5964 }
5965
5966 @Override
5967 public String toString() {
5968 return "SharedUserSetting{"
5969 + Integer.toHexString(System.identityHashCode(this))
5970 + " " + name + "/" + userId + "}";
5971 }
5972 }
5973
5974 /**
5975 * Holds information about dynamic settings.
5976 */
5977 private static final class Settings {
5978 private final File mSettingsFilename;
5979 private final File mBackupSettingsFilename;
5980 private final HashMap<String, PackageSetting> mPackages =
5981 new HashMap<String, PackageSetting>();
5982 // The user's preferred packages/applications, in order of preference.
5983 // First is the most preferred.
5984 private final ArrayList<PackageSetting> mPreferredPackages =
5985 new ArrayList<PackageSetting>();
5986 // List of replaced system applications
5987 final HashMap<String, PackageSetting> mDisabledSysPackages =
5988 new HashMap<String, PackageSetting>();
5989
5990 // The user's preferred activities associated with particular intent
5991 // filters.
5992 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5993 new IntentResolver<PreferredActivity, PreferredActivity>() {
5994 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005995 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005997 out.print(prefix); out.print(
5998 Integer.toHexString(System.identityHashCode(filter)));
5999 out.print(' ');
6000 out.print(filter.mActivity.flattenToShortString());
6001 out.print(" match=0x");
6002 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006004 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006005 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006006 out.print(prefix); out.print(" ");
6007 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 }
6009 }
6010 }
6011 };
6012 private final HashMap<String, SharedUserSetting> mSharedUsers =
6013 new HashMap<String, SharedUserSetting>();
6014 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6015 private final SparseArray<Object> mOtherUserIds =
6016 new SparseArray<Object>();
6017
6018 // For reading/writing settings file.
6019 private final ArrayList<Signature> mPastSignatures =
6020 new ArrayList<Signature>();
6021
6022 // Mapping from permission names to info about them.
6023 final HashMap<String, BasePermission> mPermissions =
6024 new HashMap<String, BasePermission>();
6025
6026 // Mapping from permission tree names to info about them.
6027 final HashMap<String, BasePermission> mPermissionTrees =
6028 new HashMap<String, BasePermission>();
6029
6030 private final ArrayList<String> mPendingPreferredPackages
6031 = new ArrayList<String>();
6032
6033 private final StringBuilder mReadMessages = new StringBuilder();
6034
6035 private static final class PendingPackage extends PackageSettingBase {
6036 final int sharedId;
6037
6038 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006039 int sharedId, int pVersionCode, int pkgFlags) {
6040 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 this.sharedId = sharedId;
6042 }
6043 }
6044 private final ArrayList<PendingPackage> mPendingPackages
6045 = new ArrayList<PendingPackage>();
6046
6047 Settings() {
6048 File dataDir = Environment.getDataDirectory();
6049 File systemDir = new File(dataDir, "system");
6050 systemDir.mkdirs();
6051 FileUtils.setPermissions(systemDir.toString(),
6052 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6053 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6054 -1, -1);
6055 mSettingsFilename = new File(systemDir, "packages.xml");
6056 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6057 }
6058
6059 PackageSetting getPackageLP(PackageParser.Package pkg,
6060 SharedUserSetting sharedUser, File codePath, File resourcePath,
6061 int pkgFlags, boolean create, boolean add) {
6062 final String name = pkg.packageName;
6063 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006064 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 return p;
6066 }
6067
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006068 PackageSetting peekPackageLP(String name) {
6069 return mPackages.get(name);
6070 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 PackageSetting p = mPackages.get(name);
6072 if (p != null && p.codePath.getPath().equals(codePath)) {
6073 return p;
6074 }
6075 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006076 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 }
6078
6079 void setInstallStatus(String pkgName, int status) {
6080 PackageSetting p = mPackages.get(pkgName);
6081 if(p != null) {
6082 if(p.getInstallStatus() != status) {
6083 p.setInstallStatus(status);
6084 }
6085 }
6086 }
6087
Jacek Surazski65e13172009-04-28 15:26:38 +02006088 void setInstallerPackageName(String pkgName,
6089 String installerPkgName) {
6090 PackageSetting p = mPackages.get(pkgName);
6091 if(p != null) {
6092 p.setInstallerPackageName(installerPkgName);
6093 }
6094 }
6095
6096 String getInstallerPackageName(String pkgName) {
6097 PackageSetting p = mPackages.get(pkgName);
6098 return (p == null) ? null : p.getInstallerPackageName();
6099 }
6100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 int getInstallStatus(String pkgName) {
6102 PackageSetting p = mPackages.get(pkgName);
6103 if(p != null) {
6104 return p.getInstallStatus();
6105 }
6106 return -1;
6107 }
6108
6109 SharedUserSetting getSharedUserLP(String name,
6110 int pkgFlags, boolean create) {
6111 SharedUserSetting s = mSharedUsers.get(name);
6112 if (s == null) {
6113 if (!create) {
6114 return null;
6115 }
6116 s = new SharedUserSetting(name, pkgFlags);
6117 if (MULTIPLE_APPLICATION_UIDS) {
6118 s.userId = newUserIdLP(s);
6119 } else {
6120 s.userId = FIRST_APPLICATION_UID;
6121 }
6122 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6123 // < 0 means we couldn't assign a userid; fall out and return
6124 // s, which is currently null
6125 if (s.userId >= 0) {
6126 mSharedUsers.put(name, s);
6127 }
6128 }
6129
6130 return s;
6131 }
6132
6133 int disableSystemPackageLP(String name) {
6134 PackageSetting p = mPackages.get(name);
6135 if(p == null) {
6136 Log.w(TAG, "Package:"+name+" is not an installed package");
6137 return -1;
6138 }
6139 PackageSetting dp = mDisabledSysPackages.get(name);
6140 // always make sure the system package code and resource paths dont change
6141 if(dp == null) {
6142 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6143 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6144 }
6145 mDisabledSysPackages.put(name, p);
6146 }
6147 return removePackageLP(name);
6148 }
6149
6150 PackageSetting enableSystemPackageLP(String name) {
6151 PackageSetting p = mDisabledSysPackages.get(name);
6152 if(p == null) {
6153 Log.w(TAG, "Package:"+name+" is not disabled");
6154 return null;
6155 }
6156 // Reset flag in ApplicationInfo object
6157 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6158 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6159 }
6160 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006161 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 mDisabledSysPackages.remove(name);
6163 return ret;
6164 }
6165
6166 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006167 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 PackageSetting p = mPackages.get(name);
6169 if (p != null) {
6170 if (p.userId == uid) {
6171 return p;
6172 }
6173 reportSettingsProblem(Log.ERROR,
6174 "Adding duplicate package, keeping first: " + name);
6175 return null;
6176 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006177 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 p.userId = uid;
6179 if (addUserIdLP(uid, p, name)) {
6180 mPackages.put(name, p);
6181 return p;
6182 }
6183 return null;
6184 }
6185
6186 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6187 SharedUserSetting s = mSharedUsers.get(name);
6188 if (s != null) {
6189 if (s.userId == uid) {
6190 return s;
6191 }
6192 reportSettingsProblem(Log.ERROR,
6193 "Adding duplicate shared user, keeping first: " + name);
6194 return null;
6195 }
6196 s = new SharedUserSetting(name, pkgFlags);
6197 s.userId = uid;
6198 if (addUserIdLP(uid, s, name)) {
6199 mSharedUsers.put(name, s);
6200 return s;
6201 }
6202 return null;
6203 }
6204
6205 private PackageSetting getPackageLP(String name,
6206 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006207 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 PackageSetting p = mPackages.get(name);
6209 if (p != null) {
6210 if (!p.codePath.equals(codePath)) {
6211 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006212 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006213 // This is an updated system app with versions in both system
6214 // and data partition. Just let the most recent version
6215 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006216 Log.w(TAG, "Trying to update system app code path from " +
6217 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006218 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006219 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006220 reportSettingsProblem(Log.WARN,
6221 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006222 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006224 }
6225 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006226 reportSettingsProblem(Log.WARN,
6227 "Package " + name + " shared user changed from "
6228 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6229 + " to "
6230 + (sharedUser != null ? sharedUser.name : "<nothing>")
6231 + "; replacing with new");
6232 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006233 } else {
6234 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6235 // If what we are scanning is a system package, then
6236 // make it so, regardless of whether it was previously
6237 // installed only in the data partition.
6238 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 }
6241 }
6242 if (p == null) {
6243 // Create a new PackageSettings entry. this can end up here because
6244 // of code path mismatch or user id mismatch of an updated system partition
6245 if (!create) {
6246 return null;
6247 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006248 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006250 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 if (sharedUser != null) {
6252 p.userId = sharedUser.userId;
6253 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006254 // Clone the setting here for disabled system packages
6255 PackageSetting dis = mDisabledSysPackages.get(name);
6256 if (dis != null) {
6257 // For disabled packages a new setting is created
6258 // from the existing user id. This still has to be
6259 // added to list of user id's
6260 // Copy signatures from previous setting
6261 if (dis.signatures.mSignatures != null) {
6262 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6263 }
6264 p.userId = dis.userId;
6265 // Clone permissions
6266 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6267 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6268 // Clone component info
6269 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6270 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6271 // Add new setting to list of user ids
6272 addUserIdLP(p.userId, p, name);
6273 } else {
6274 // Assign new user id
6275 p.userId = newUserIdLP(p);
6276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 } else {
6278 p.userId = FIRST_APPLICATION_UID;
6279 }
6280 if (p.userId < 0) {
6281 reportSettingsProblem(Log.WARN,
6282 "Package " + name + " could not be assigned a valid uid");
6283 return null;
6284 }
6285 if (add) {
6286 // Finish adding new package by adding it and updating shared
6287 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006288 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 }
6290 }
6291 return p;
6292 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006293
6294 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6295 File codePath, File resourcePath) {
6296 p.pkg = pkg;
6297 // Update code path if needed
6298 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6299 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006300 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006301 p.codePath = codePath;
6302 p.codePathString = codePath.toString();
6303 }
6304 //Update resource path if needed
6305 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6306 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006307 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006308 p.resourcePath = resourcePath;
6309 p.resourcePathString = resourcePath.toString();
6310 }
6311 // Update version code if needed
6312 if (pkg.mVersionCode != p.versionCode) {
6313 p.versionCode = pkg.mVersionCode;
6314 }
6315 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6316 }
6317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 // Utility method that adds a PackageSetting to mPackages and
6319 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006320 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321 SharedUserSetting sharedUser) {
6322 mPackages.put(name, p);
6323 if (sharedUser != null) {
6324 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6325 reportSettingsProblem(Log.ERROR,
6326 "Package " + p.name + " was user "
6327 + p.sharedUser + " but is now " + sharedUser
6328 + "; I am not changing its files so it will probably fail!");
6329 p.sharedUser.packages.remove(p);
6330 } else if (p.userId != sharedUser.userId) {
6331 reportSettingsProblem(Log.ERROR,
6332 "Package " + p.name + " was user id " + p.userId
6333 + " but is now user " + sharedUser
6334 + " with id " + sharedUser.userId
6335 + "; I am not changing its files so it will probably fail!");
6336 }
6337
6338 sharedUser.packages.add(p);
6339 p.sharedUser = sharedUser;
6340 p.userId = sharedUser.userId;
6341 }
6342 }
6343
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006344 /*
6345 * Update the shared user setting when a package using
6346 * specifying the shared user id is removed. The gids
6347 * associated with each permission of the deleted package
6348 * are removed from the shared user's gid list only if its
6349 * not in use by other permissions of packages in the
6350 * shared user setting.
6351 */
6352 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006353 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6354 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6355 return;
6356 }
6357 // No sharedUserId
6358 if (deletedPs.sharedUser == null) {
6359 return;
6360 }
6361 SharedUserSetting sus = deletedPs.sharedUser;
6362 // Update permissions
6363 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6364 boolean used = false;
6365 if (!sus.grantedPermissions.contains (eachPerm)) {
6366 continue;
6367 }
6368 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006369 if (pkg.pkg != null &&
6370 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6371 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 used = true;
6373 break;
6374 }
6375 }
6376 if (!used) {
6377 // can safely delete this permission from list
6378 sus.grantedPermissions.remove(eachPerm);
6379 sus.loadedPermissions.remove(eachPerm);
6380 }
6381 }
6382 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006383 int newGids[] = globalGids;
6384 for (String eachPerm : sus.grantedPermissions) {
6385 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006386 if (bp != null) {
6387 newGids = appendInts(newGids, bp.gids);
6388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006389 }
6390 sus.gids = newGids;
6391 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 private int removePackageLP(String name) {
6394 PackageSetting p = mPackages.get(name);
6395 if (p != null) {
6396 mPackages.remove(name);
6397 if (p.sharedUser != null) {
6398 p.sharedUser.packages.remove(p);
6399 if (p.sharedUser.packages.size() == 0) {
6400 mSharedUsers.remove(p.sharedUser.name);
6401 removeUserIdLP(p.sharedUser.userId);
6402 return p.sharedUser.userId;
6403 }
6404 } else {
6405 removeUserIdLP(p.userId);
6406 return p.userId;
6407 }
6408 }
6409 return -1;
6410 }
6411
6412 private boolean addUserIdLP(int uid, Object obj, Object name) {
6413 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6414 return false;
6415 }
6416
6417 if (uid >= FIRST_APPLICATION_UID) {
6418 int N = mUserIds.size();
6419 final int index = uid - FIRST_APPLICATION_UID;
6420 while (index >= N) {
6421 mUserIds.add(null);
6422 N++;
6423 }
6424 if (mUserIds.get(index) != null) {
6425 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006426 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006427 + " name=" + name);
6428 return false;
6429 }
6430 mUserIds.set(index, obj);
6431 } else {
6432 if (mOtherUserIds.get(uid) != null) {
6433 reportSettingsProblem(Log.ERROR,
6434 "Adding duplicate shared id: " + uid
6435 + " name=" + name);
6436 return false;
6437 }
6438 mOtherUserIds.put(uid, obj);
6439 }
6440 return true;
6441 }
6442
6443 public Object getUserIdLP(int uid) {
6444 if (uid >= FIRST_APPLICATION_UID) {
6445 int N = mUserIds.size();
6446 final int index = uid - FIRST_APPLICATION_UID;
6447 return index < N ? mUserIds.get(index) : null;
6448 } else {
6449 return mOtherUserIds.get(uid);
6450 }
6451 }
6452
6453 private void removeUserIdLP(int uid) {
6454 if (uid >= FIRST_APPLICATION_UID) {
6455 int N = mUserIds.size();
6456 final int index = uid - FIRST_APPLICATION_UID;
6457 if (index < N) mUserIds.set(index, null);
6458 } else {
6459 mOtherUserIds.remove(uid);
6460 }
6461 }
6462
6463 void writeLP() {
6464 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6465
6466 // Keep the old settings around until we know the new ones have
6467 // been successfully written.
6468 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006469 // Presence of backup settings file indicates that we failed
6470 // to persist settings earlier. So preserve the older
6471 // backup for future reference since the current settings
6472 // might have been corrupted.
6473 if (!mBackupSettingsFilename.exists()) {
6474 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6475 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6476 return;
6477 }
6478 } else {
6479 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 }
6482
6483 mPastSignatures.clear();
6484
6485 try {
6486 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6487
6488 //XmlSerializer serializer = XmlUtils.serializerInstance();
6489 XmlSerializer serializer = new FastXmlSerializer();
6490 serializer.setOutput(str, "utf-8");
6491 serializer.startDocument(null, true);
6492 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6493
6494 serializer.startTag(null, "packages");
6495
6496 serializer.startTag(null, "permission-trees");
6497 for (BasePermission bp : mPermissionTrees.values()) {
6498 writePermission(serializer, bp);
6499 }
6500 serializer.endTag(null, "permission-trees");
6501
6502 serializer.startTag(null, "permissions");
6503 for (BasePermission bp : mPermissions.values()) {
6504 writePermission(serializer, bp);
6505 }
6506 serializer.endTag(null, "permissions");
6507
6508 for (PackageSetting pkg : mPackages.values()) {
6509 writePackage(serializer, pkg);
6510 }
6511
6512 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6513 writeDisabledSysPackage(serializer, pkg);
6514 }
6515
6516 serializer.startTag(null, "preferred-packages");
6517 int N = mPreferredPackages.size();
6518 for (int i=0; i<N; i++) {
6519 PackageSetting pkg = mPreferredPackages.get(i);
6520 serializer.startTag(null, "item");
6521 serializer.attribute(null, "name", pkg.name);
6522 serializer.endTag(null, "item");
6523 }
6524 serializer.endTag(null, "preferred-packages");
6525
6526 serializer.startTag(null, "preferred-activities");
6527 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6528 serializer.startTag(null, "item");
6529 pa.writeToXml(serializer);
6530 serializer.endTag(null, "item");
6531 }
6532 serializer.endTag(null, "preferred-activities");
6533
6534 for (SharedUserSetting usr : mSharedUsers.values()) {
6535 serializer.startTag(null, "shared-user");
6536 serializer.attribute(null, "name", usr.name);
6537 serializer.attribute(null, "userId",
6538 Integer.toString(usr.userId));
6539 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6540 serializer.startTag(null, "perms");
6541 for (String name : usr.grantedPermissions) {
6542 serializer.startTag(null, "item");
6543 serializer.attribute(null, "name", name);
6544 serializer.endTag(null, "item");
6545 }
6546 serializer.endTag(null, "perms");
6547 serializer.endTag(null, "shared-user");
6548 }
6549
6550 serializer.endTag(null, "packages");
6551
6552 serializer.endDocument();
6553
6554 str.flush();
6555 str.close();
6556
6557 // New settings successfully written, old ones are no longer
6558 // needed.
6559 mBackupSettingsFilename.delete();
6560 FileUtils.setPermissions(mSettingsFilename.toString(),
6561 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6562 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6563 |FileUtils.S_IROTH,
6564 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006565 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566
6567 } catch(XmlPullParserException e) {
6568 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 -08006569 } catch(java.io.IOException e) {
6570 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 -08006571 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006572 // Clean up partially written file
6573 if (mSettingsFilename.exists()) {
6574 if (!mSettingsFilename.delete()) {
6575 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6576 }
6577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006578 //Debug.stopMethodTracing();
6579 }
6580
6581 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
6582 throws java.io.IOException {
6583 serializer.startTag(null, "updated-package");
6584 serializer.attribute(null, "name", pkg.name);
6585 serializer.attribute(null, "codePath", pkg.codePathString);
6586 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006587 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006588 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6589 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6590 }
6591 if (pkg.sharedUser == null) {
6592 serializer.attribute(null, "userId",
6593 Integer.toString(pkg.userId));
6594 } else {
6595 serializer.attribute(null, "sharedUserId",
6596 Integer.toString(pkg.userId));
6597 }
6598 serializer.startTag(null, "perms");
6599 if (pkg.sharedUser == null) {
6600 // If this is a shared user, the permissions will
6601 // be written there. We still need to write an
6602 // empty permissions list so permissionsFixed will
6603 // be set.
6604 for (final String name : pkg.grantedPermissions) {
6605 BasePermission bp = mPermissions.get(name);
6606 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6607 // We only need to write signature or system permissions but this wont
6608 // match the semantics of grantedPermissions. So write all permissions.
6609 serializer.startTag(null, "item");
6610 serializer.attribute(null, "name", name);
6611 serializer.endTag(null, "item");
6612 }
6613 }
6614 }
6615 serializer.endTag(null, "perms");
6616 serializer.endTag(null, "updated-package");
6617 }
6618
6619 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6620 throws java.io.IOException {
6621 serializer.startTag(null, "package");
6622 serializer.attribute(null, "name", pkg.name);
6623 serializer.attribute(null, "codePath", pkg.codePathString);
6624 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6625 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6626 }
6627 serializer.attribute(null, "system",
6628 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6629 ? "true" : "false");
6630 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006631 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006632 if (pkg.sharedUser == null) {
6633 serializer.attribute(null, "userId",
6634 Integer.toString(pkg.userId));
6635 } else {
6636 serializer.attribute(null, "sharedUserId",
6637 Integer.toString(pkg.userId));
6638 }
6639 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6640 serializer.attribute(null, "enabled",
6641 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6642 ? "true" : "false");
6643 }
6644 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6645 serializer.attribute(null, "installStatus", "false");
6646 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006647 if (pkg.installerPackageName != null) {
6648 serializer.attribute(null, "installer", pkg.installerPackageName);
6649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6651 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6652 serializer.startTag(null, "perms");
6653 if (pkg.sharedUser == null) {
6654 // If this is a shared user, the permissions will
6655 // be written there. We still need to write an
6656 // empty permissions list so permissionsFixed will
6657 // be set.
6658 for (final String name : pkg.grantedPermissions) {
6659 serializer.startTag(null, "item");
6660 serializer.attribute(null, "name", name);
6661 serializer.endTag(null, "item");
6662 }
6663 }
6664 serializer.endTag(null, "perms");
6665 }
6666 if (pkg.disabledComponents.size() > 0) {
6667 serializer.startTag(null, "disabled-components");
6668 for (final String name : pkg.disabledComponents) {
6669 serializer.startTag(null, "item");
6670 serializer.attribute(null, "name", name);
6671 serializer.endTag(null, "item");
6672 }
6673 serializer.endTag(null, "disabled-components");
6674 }
6675 if (pkg.enabledComponents.size() > 0) {
6676 serializer.startTag(null, "enabled-components");
6677 for (final String name : pkg.enabledComponents) {
6678 serializer.startTag(null, "item");
6679 serializer.attribute(null, "name", name);
6680 serializer.endTag(null, "item");
6681 }
6682 serializer.endTag(null, "enabled-components");
6683 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006685 serializer.endTag(null, "package");
6686 }
6687
6688 void writePermission(XmlSerializer serializer, BasePermission bp)
6689 throws XmlPullParserException, java.io.IOException {
6690 if (bp.type != BasePermission.TYPE_BUILTIN
6691 && bp.sourcePackage != null) {
6692 serializer.startTag(null, "item");
6693 serializer.attribute(null, "name", bp.name);
6694 serializer.attribute(null, "package", bp.sourcePackage);
6695 if (DEBUG_SETTINGS) Log.v(TAG,
6696 "Writing perm: name=" + bp.name + " type=" + bp.type);
6697 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6698 PermissionInfo pi = bp.perm != null ? bp.perm.info
6699 : bp.pendingInfo;
6700 if (pi != null) {
6701 serializer.attribute(null, "type", "dynamic");
6702 if (pi.icon != 0) {
6703 serializer.attribute(null, "icon",
6704 Integer.toString(pi.icon));
6705 }
6706 if (pi.nonLocalizedLabel != null) {
6707 serializer.attribute(null, "label",
6708 pi.nonLocalizedLabel.toString());
6709 }
6710 if (pi.protectionLevel !=
6711 PermissionInfo.PROTECTION_NORMAL) {
6712 serializer.attribute(null, "protection",
6713 Integer.toString(pi.protectionLevel));
6714 }
6715 }
6716 }
6717 serializer.endTag(null, "item");
6718 }
6719 }
6720
6721 String getReadMessagesLP() {
6722 return mReadMessages.toString();
6723 }
6724
6725 ArrayList<String> getListOfIncompleteInstallPackages() {
6726 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6727 Iterator<String> its = kList.iterator();
6728 ArrayList<String> ret = new ArrayList<String>();
6729 while(its.hasNext()) {
6730 String key = its.next();
6731 PackageSetting ps = mPackages.get(key);
6732 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6733 ret.add(key);
6734 }
6735 }
6736 return ret;
6737 }
6738
6739 boolean readLP() {
6740 FileInputStream str = null;
6741 if (mBackupSettingsFilename.exists()) {
6742 try {
6743 str = new FileInputStream(mBackupSettingsFilename);
6744 mReadMessages.append("Reading from backup settings file\n");
6745 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006746 if (mSettingsFilename.exists()) {
6747 // If both the backup and settings file exist, we
6748 // ignore the settings since it might have been
6749 // corrupted.
6750 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6751 mSettingsFilename.delete();
6752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006753 } catch (java.io.IOException e) {
6754 // We'll try for the normal settings file.
6755 }
6756 }
6757
6758 mPastSignatures.clear();
6759
6760 try {
6761 if (str == null) {
6762 if (!mSettingsFilename.exists()) {
6763 mReadMessages.append("No settings file found\n");
6764 Log.i(TAG, "No current settings file!");
6765 return false;
6766 }
6767 str = new FileInputStream(mSettingsFilename);
6768 }
6769 XmlPullParser parser = Xml.newPullParser();
6770 parser.setInput(str, null);
6771
6772 int type;
6773 while ((type=parser.next()) != XmlPullParser.START_TAG
6774 && type != XmlPullParser.END_DOCUMENT) {
6775 ;
6776 }
6777
6778 if (type != XmlPullParser.START_TAG) {
6779 mReadMessages.append("No start tag found in settings file\n");
6780 Log.e(TAG, "No start tag found in package manager settings");
6781 return false;
6782 }
6783
6784 int outerDepth = parser.getDepth();
6785 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6786 && (type != XmlPullParser.END_TAG
6787 || parser.getDepth() > outerDepth)) {
6788 if (type == XmlPullParser.END_TAG
6789 || type == XmlPullParser.TEXT) {
6790 continue;
6791 }
6792
6793 String tagName = parser.getName();
6794 if (tagName.equals("package")) {
6795 readPackageLP(parser);
6796 } else if (tagName.equals("permissions")) {
6797 readPermissionsLP(mPermissions, parser);
6798 } else if (tagName.equals("permission-trees")) {
6799 readPermissionsLP(mPermissionTrees, parser);
6800 } else if (tagName.equals("shared-user")) {
6801 readSharedUserLP(parser);
6802 } else if (tagName.equals("preferred-packages")) {
6803 readPreferredPackagesLP(parser);
6804 } else if (tagName.equals("preferred-activities")) {
6805 readPreferredActivitiesLP(parser);
6806 } else if(tagName.equals("updated-package")) {
6807 readDisabledSysPackageLP(parser);
6808 } else {
6809 Log.w(TAG, "Unknown element under <packages>: "
6810 + parser.getName());
6811 XmlUtils.skipCurrentTag(parser);
6812 }
6813 }
6814
6815 str.close();
6816
6817 } catch(XmlPullParserException e) {
6818 mReadMessages.append("Error reading: " + e.toString());
6819 Log.e(TAG, "Error reading package manager settings", e);
6820
6821 } catch(java.io.IOException e) {
6822 mReadMessages.append("Error reading: " + e.toString());
6823 Log.e(TAG, "Error reading package manager settings", e);
6824
6825 }
6826
6827 int N = mPendingPackages.size();
6828 for (int i=0; i<N; i++) {
6829 final PendingPackage pp = mPendingPackages.get(i);
6830 Object idObj = getUserIdLP(pp.sharedId);
6831 if (idObj != null && idObj instanceof SharedUserSetting) {
6832 PackageSetting p = getPackageLP(pp.name,
6833 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006834 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 if (p == null) {
6836 Log.w(TAG, "Unable to create application package for "
6837 + pp.name);
6838 continue;
6839 }
6840 p.copyFrom(pp);
6841 } else if (idObj != null) {
6842 String msg = "Bad package setting: package " + pp.name
6843 + " has shared uid " + pp.sharedId
6844 + " that is not a shared uid\n";
6845 mReadMessages.append(msg);
6846 Log.e(TAG, msg);
6847 } else {
6848 String msg = "Bad package setting: package " + pp.name
6849 + " has shared uid " + pp.sharedId
6850 + " that is not defined\n";
6851 mReadMessages.append(msg);
6852 Log.e(TAG, msg);
6853 }
6854 }
6855 mPendingPackages.clear();
6856
6857 N = mPendingPreferredPackages.size();
6858 mPreferredPackages.clear();
6859 for (int i=0; i<N; i++) {
6860 final String name = mPendingPreferredPackages.get(i);
6861 final PackageSetting p = mPackages.get(name);
6862 if (p != null) {
6863 mPreferredPackages.add(p);
6864 } else {
6865 Log.w(TAG, "Unknown preferred package: " + name);
6866 }
6867 }
6868 mPendingPreferredPackages.clear();
6869
6870 mReadMessages.append("Read completed successfully: "
6871 + mPackages.size() + " packages, "
6872 + mSharedUsers.size() + " shared uids\n");
6873
6874 return true;
6875 }
6876
6877 private int readInt(XmlPullParser parser, String ns, String name,
6878 int defValue) {
6879 String v = parser.getAttributeValue(ns, name);
6880 try {
6881 if (v == null) {
6882 return defValue;
6883 }
6884 return Integer.parseInt(v);
6885 } catch (NumberFormatException e) {
6886 reportSettingsProblem(Log.WARN,
6887 "Error in package manager settings: attribute " +
6888 name + " has bad integer value " + v + " at "
6889 + parser.getPositionDescription());
6890 }
6891 return defValue;
6892 }
6893
6894 private void readPermissionsLP(HashMap<String, BasePermission> out,
6895 XmlPullParser parser)
6896 throws IOException, XmlPullParserException {
6897 int outerDepth = parser.getDepth();
6898 int type;
6899 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6900 && (type != XmlPullParser.END_TAG
6901 || parser.getDepth() > outerDepth)) {
6902 if (type == XmlPullParser.END_TAG
6903 || type == XmlPullParser.TEXT) {
6904 continue;
6905 }
6906
6907 String tagName = parser.getName();
6908 if (tagName.equals("item")) {
6909 String name = parser.getAttributeValue(null, "name");
6910 String sourcePackage = parser.getAttributeValue(null, "package");
6911 String ptype = parser.getAttributeValue(null, "type");
6912 if (name != null && sourcePackage != null) {
6913 boolean dynamic = "dynamic".equals(ptype);
6914 BasePermission bp = new BasePermission(name, sourcePackage,
6915 dynamic
6916 ? BasePermission.TYPE_DYNAMIC
6917 : BasePermission.TYPE_NORMAL);
6918 if (dynamic) {
6919 PermissionInfo pi = new PermissionInfo();
6920 pi.packageName = sourcePackage.intern();
6921 pi.name = name.intern();
6922 pi.icon = readInt(parser, null, "icon", 0);
6923 pi.nonLocalizedLabel = parser.getAttributeValue(
6924 null, "label");
6925 pi.protectionLevel = readInt(parser, null, "protection",
6926 PermissionInfo.PROTECTION_NORMAL);
6927 bp.pendingInfo = pi;
6928 }
6929 out.put(bp.name, bp);
6930 } else {
6931 reportSettingsProblem(Log.WARN,
6932 "Error in package manager settings: permissions has"
6933 + " no name at " + parser.getPositionDescription());
6934 }
6935 } else {
6936 reportSettingsProblem(Log.WARN,
6937 "Unknown element reading permissions: "
6938 + parser.getName() + " at "
6939 + parser.getPositionDescription());
6940 }
6941 XmlUtils.skipCurrentTag(parser);
6942 }
6943 }
6944
6945 private void readDisabledSysPackageLP(XmlPullParser parser)
6946 throws XmlPullParserException, IOException {
6947 String name = parser.getAttributeValue(null, "name");
6948 String codePathStr = parser.getAttributeValue(null, "codePath");
6949 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6950 if(resourcePathStr == null) {
6951 resourcePathStr = codePathStr;
6952 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006953 String version = parser.getAttributeValue(null, "version");
6954 int versionCode = 0;
6955 if (version != null) {
6956 try {
6957 versionCode = Integer.parseInt(version);
6958 } catch (NumberFormatException e) {
6959 }
6960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961
6962 int pkgFlags = 0;
6963 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6964 PackageSetting ps = new PackageSetting(name,
6965 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006966 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 String timeStampStr = parser.getAttributeValue(null, "ts");
6968 if (timeStampStr != null) {
6969 try {
6970 long timeStamp = Long.parseLong(timeStampStr);
6971 ps.setTimeStamp(timeStamp, timeStampStr);
6972 } catch (NumberFormatException e) {
6973 }
6974 }
6975 String idStr = parser.getAttributeValue(null, "userId");
6976 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6977 if(ps.userId <= 0) {
6978 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6979 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6980 }
6981 int outerDepth = parser.getDepth();
6982 int type;
6983 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6984 && (type != XmlPullParser.END_TAG
6985 || parser.getDepth() > outerDepth)) {
6986 if (type == XmlPullParser.END_TAG
6987 || type == XmlPullParser.TEXT) {
6988 continue;
6989 }
6990
6991 String tagName = parser.getName();
6992 if (tagName.equals("perms")) {
6993 readGrantedPermissionsLP(parser,
6994 ps.grantedPermissions);
6995 } else {
6996 reportSettingsProblem(Log.WARN,
6997 "Unknown element under <updated-package>: "
6998 + parser.getName());
6999 XmlUtils.skipCurrentTag(parser);
7000 }
7001 }
7002 mDisabledSysPackages.put(name, ps);
7003 }
7004
7005 private void readPackageLP(XmlPullParser parser)
7006 throws XmlPullParserException, IOException {
7007 String name = null;
7008 String idStr = null;
7009 String sharedIdStr = null;
7010 String codePathStr = null;
7011 String resourcePathStr = null;
7012 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007013 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 int pkgFlags = 0;
7015 String timeStampStr;
7016 long timeStamp = 0;
7017 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007018 String version = null;
7019 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 try {
7021 name = parser.getAttributeValue(null, "name");
7022 idStr = parser.getAttributeValue(null, "userId");
7023 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7024 codePathStr = parser.getAttributeValue(null, "codePath");
7025 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007026 version = parser.getAttributeValue(null, "version");
7027 if (version != null) {
7028 try {
7029 versionCode = Integer.parseInt(version);
7030 } catch (NumberFormatException e) {
7031 }
7032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007033 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007034 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007035 if (systemStr != null) {
7036 if ("true".equals(systemStr)) {
7037 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7038 }
7039 } else {
7040 // Old settings that don't specify system... just treat
7041 // them as system, good enough.
7042 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7043 }
7044 timeStampStr = parser.getAttributeValue(null, "ts");
7045 if (timeStampStr != null) {
7046 try {
7047 timeStamp = Long.parseLong(timeStampStr);
7048 } catch (NumberFormatException e) {
7049 }
7050 }
7051 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7052 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7053 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7054 if (resourcePathStr == null) {
7055 resourcePathStr = codePathStr;
7056 }
7057 if (name == null) {
7058 reportSettingsProblem(Log.WARN,
7059 "Error in package manager settings: <package> has no name at "
7060 + parser.getPositionDescription());
7061 } else if (codePathStr == null) {
7062 reportSettingsProblem(Log.WARN,
7063 "Error in package manager settings: <package> has no codePath at "
7064 + parser.getPositionDescription());
7065 } else if (userId > 0) {
7066 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007067 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7069 + ": userId=" + userId + " pkg=" + packageSetting);
7070 if (packageSetting == null) {
7071 reportSettingsProblem(Log.ERROR,
7072 "Failure adding uid " + userId
7073 + " while parsing settings at "
7074 + parser.getPositionDescription());
7075 } else {
7076 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7077 }
7078 } else if (sharedIdStr != null) {
7079 userId = sharedIdStr != null
7080 ? Integer.parseInt(sharedIdStr) : 0;
7081 if (userId > 0) {
7082 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007083 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007084 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7085 mPendingPackages.add((PendingPackage) packageSetting);
7086 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7087 + ": sharedUserId=" + userId + " pkg="
7088 + packageSetting);
7089 } else {
7090 reportSettingsProblem(Log.WARN,
7091 "Error in package manager settings: package "
7092 + name + " has bad sharedId " + sharedIdStr
7093 + " at " + parser.getPositionDescription());
7094 }
7095 } else {
7096 reportSettingsProblem(Log.WARN,
7097 "Error in package manager settings: package "
7098 + name + " has bad userId " + idStr + " at "
7099 + parser.getPositionDescription());
7100 }
7101 } catch (NumberFormatException e) {
7102 reportSettingsProblem(Log.WARN,
7103 "Error in package manager settings: package "
7104 + name + " has bad userId " + idStr + " at "
7105 + parser.getPositionDescription());
7106 }
7107 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007108 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007109 final String enabledStr = parser.getAttributeValue(null, "enabled");
7110 if (enabledStr != null) {
7111 if (enabledStr.equalsIgnoreCase("true")) {
7112 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7113 } else if (enabledStr.equalsIgnoreCase("false")) {
7114 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7115 } else if (enabledStr.equalsIgnoreCase("default")) {
7116 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7117 } else {
7118 reportSettingsProblem(Log.WARN,
7119 "Error in package manager settings: package "
7120 + name + " has bad enabled value: " + idStr
7121 + " at " + parser.getPositionDescription());
7122 }
7123 } else {
7124 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7125 }
7126 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7127 if (installStatusStr != null) {
7128 if (installStatusStr.equalsIgnoreCase("false")) {
7129 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7130 } else {
7131 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7132 }
7133 }
7134
7135 int outerDepth = parser.getDepth();
7136 int type;
7137 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7138 && (type != XmlPullParser.END_TAG
7139 || parser.getDepth() > outerDepth)) {
7140 if (type == XmlPullParser.END_TAG
7141 || type == XmlPullParser.TEXT) {
7142 continue;
7143 }
7144
7145 String tagName = parser.getName();
7146 if (tagName.equals("disabled-components")) {
7147 readDisabledComponentsLP(packageSetting, parser);
7148 } else if (tagName.equals("enabled-components")) {
7149 readEnabledComponentsLP(packageSetting, parser);
7150 } else if (tagName.equals("sigs")) {
7151 packageSetting.signatures.readXml(parser, mPastSignatures);
7152 } else if (tagName.equals("perms")) {
7153 readGrantedPermissionsLP(parser,
7154 packageSetting.loadedPermissions);
7155 packageSetting.permissionsFixed = true;
7156 } else {
7157 reportSettingsProblem(Log.WARN,
7158 "Unknown element under <package>: "
7159 + parser.getName());
7160 XmlUtils.skipCurrentTag(parser);
7161 }
7162 }
7163 } else {
7164 XmlUtils.skipCurrentTag(parser);
7165 }
7166 }
7167
7168 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7169 XmlPullParser parser)
7170 throws IOException, XmlPullParserException {
7171 int outerDepth = parser.getDepth();
7172 int type;
7173 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7174 && (type != XmlPullParser.END_TAG
7175 || parser.getDepth() > outerDepth)) {
7176 if (type == XmlPullParser.END_TAG
7177 || type == XmlPullParser.TEXT) {
7178 continue;
7179 }
7180
7181 String tagName = parser.getName();
7182 if (tagName.equals("item")) {
7183 String name = parser.getAttributeValue(null, "name");
7184 if (name != null) {
7185 packageSetting.disabledComponents.add(name.intern());
7186 } else {
7187 reportSettingsProblem(Log.WARN,
7188 "Error in package manager settings: <disabled-components> has"
7189 + " no name at " + parser.getPositionDescription());
7190 }
7191 } else {
7192 reportSettingsProblem(Log.WARN,
7193 "Unknown element under <disabled-components>: "
7194 + parser.getName());
7195 }
7196 XmlUtils.skipCurrentTag(parser);
7197 }
7198 }
7199
7200 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7201 XmlPullParser parser)
7202 throws IOException, XmlPullParserException {
7203 int outerDepth = parser.getDepth();
7204 int type;
7205 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7206 && (type != XmlPullParser.END_TAG
7207 || parser.getDepth() > outerDepth)) {
7208 if (type == XmlPullParser.END_TAG
7209 || type == XmlPullParser.TEXT) {
7210 continue;
7211 }
7212
7213 String tagName = parser.getName();
7214 if (tagName.equals("item")) {
7215 String name = parser.getAttributeValue(null, "name");
7216 if (name != null) {
7217 packageSetting.enabledComponents.add(name.intern());
7218 } else {
7219 reportSettingsProblem(Log.WARN,
7220 "Error in package manager settings: <enabled-components> has"
7221 + " no name at " + parser.getPositionDescription());
7222 }
7223 } else {
7224 reportSettingsProblem(Log.WARN,
7225 "Unknown element under <enabled-components>: "
7226 + parser.getName());
7227 }
7228 XmlUtils.skipCurrentTag(parser);
7229 }
7230 }
7231
7232 private void readSharedUserLP(XmlPullParser parser)
7233 throws XmlPullParserException, IOException {
7234 String name = null;
7235 String idStr = null;
7236 int pkgFlags = 0;
7237 SharedUserSetting su = null;
7238 try {
7239 name = parser.getAttributeValue(null, "name");
7240 idStr = parser.getAttributeValue(null, "userId");
7241 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7242 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7243 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7244 }
7245 if (name == null) {
7246 reportSettingsProblem(Log.WARN,
7247 "Error in package manager settings: <shared-user> has no name at "
7248 + parser.getPositionDescription());
7249 } else if (userId == 0) {
7250 reportSettingsProblem(Log.WARN,
7251 "Error in package manager settings: shared-user "
7252 + name + " has bad userId " + idStr + " at "
7253 + parser.getPositionDescription());
7254 } else {
7255 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7256 reportSettingsProblem(Log.ERROR,
7257 "Occurred while parsing settings at "
7258 + parser.getPositionDescription());
7259 }
7260 }
7261 } catch (NumberFormatException e) {
7262 reportSettingsProblem(Log.WARN,
7263 "Error in package manager settings: package "
7264 + name + " has bad userId " + idStr + " at "
7265 + parser.getPositionDescription());
7266 };
7267
7268 if (su != null) {
7269 int outerDepth = parser.getDepth();
7270 int type;
7271 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7272 && (type != XmlPullParser.END_TAG
7273 || parser.getDepth() > outerDepth)) {
7274 if (type == XmlPullParser.END_TAG
7275 || type == XmlPullParser.TEXT) {
7276 continue;
7277 }
7278
7279 String tagName = parser.getName();
7280 if (tagName.equals("sigs")) {
7281 su.signatures.readXml(parser, mPastSignatures);
7282 } else if (tagName.equals("perms")) {
7283 readGrantedPermissionsLP(parser, su.loadedPermissions);
7284 } else {
7285 reportSettingsProblem(Log.WARN,
7286 "Unknown element under <shared-user>: "
7287 + parser.getName());
7288 XmlUtils.skipCurrentTag(parser);
7289 }
7290 }
7291
7292 } else {
7293 XmlUtils.skipCurrentTag(parser);
7294 }
7295 }
7296
7297 private void readGrantedPermissionsLP(XmlPullParser parser,
7298 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7299 int outerDepth = parser.getDepth();
7300 int type;
7301 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7302 && (type != XmlPullParser.END_TAG
7303 || parser.getDepth() > outerDepth)) {
7304 if (type == XmlPullParser.END_TAG
7305 || type == XmlPullParser.TEXT) {
7306 continue;
7307 }
7308
7309 String tagName = parser.getName();
7310 if (tagName.equals("item")) {
7311 String name = parser.getAttributeValue(null, "name");
7312 if (name != null) {
7313 outPerms.add(name.intern());
7314 } else {
7315 reportSettingsProblem(Log.WARN,
7316 "Error in package manager settings: <perms> has"
7317 + " no name at " + parser.getPositionDescription());
7318 }
7319 } else {
7320 reportSettingsProblem(Log.WARN,
7321 "Unknown element under <perms>: "
7322 + parser.getName());
7323 }
7324 XmlUtils.skipCurrentTag(parser);
7325 }
7326 }
7327
7328 private void readPreferredPackagesLP(XmlPullParser parser)
7329 throws XmlPullParserException, IOException {
7330 int outerDepth = parser.getDepth();
7331 int type;
7332 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7333 && (type != XmlPullParser.END_TAG
7334 || parser.getDepth() > outerDepth)) {
7335 if (type == XmlPullParser.END_TAG
7336 || type == XmlPullParser.TEXT) {
7337 continue;
7338 }
7339
7340 String tagName = parser.getName();
7341 if (tagName.equals("item")) {
7342 String name = parser.getAttributeValue(null, "name");
7343 if (name != null) {
7344 mPendingPreferredPackages.add(name);
7345 } else {
7346 reportSettingsProblem(Log.WARN,
7347 "Error in package manager settings: <preferred-package> has no name at "
7348 + parser.getPositionDescription());
7349 }
7350 } else {
7351 reportSettingsProblem(Log.WARN,
7352 "Unknown element under <preferred-packages>: "
7353 + parser.getName());
7354 }
7355 XmlUtils.skipCurrentTag(parser);
7356 }
7357 }
7358
7359 private void readPreferredActivitiesLP(XmlPullParser parser)
7360 throws XmlPullParserException, IOException {
7361 int outerDepth = parser.getDepth();
7362 int type;
7363 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7364 && (type != XmlPullParser.END_TAG
7365 || parser.getDepth() > outerDepth)) {
7366 if (type == XmlPullParser.END_TAG
7367 || type == XmlPullParser.TEXT) {
7368 continue;
7369 }
7370
7371 String tagName = parser.getName();
7372 if (tagName.equals("item")) {
7373 PreferredActivity pa = new PreferredActivity(parser);
7374 if (pa.mParseError == null) {
7375 mPreferredActivities.addFilter(pa);
7376 } else {
7377 reportSettingsProblem(Log.WARN,
7378 "Error in package manager settings: <preferred-activity> "
7379 + pa.mParseError + " at "
7380 + parser.getPositionDescription());
7381 }
7382 } else {
7383 reportSettingsProblem(Log.WARN,
7384 "Unknown element under <preferred-activities>: "
7385 + parser.getName());
7386 XmlUtils.skipCurrentTag(parser);
7387 }
7388 }
7389 }
7390
7391 // Returns -1 if we could not find an available UserId to assign
7392 private int newUserIdLP(Object obj) {
7393 // Let's be stupidly inefficient for now...
7394 final int N = mUserIds.size();
7395 for (int i=0; i<N; i++) {
7396 if (mUserIds.get(i) == null) {
7397 mUserIds.set(i, obj);
7398 return FIRST_APPLICATION_UID + i;
7399 }
7400 }
7401
7402 // None left?
7403 if (N >= MAX_APPLICATION_UIDS) {
7404 return -1;
7405 }
7406
7407 mUserIds.add(obj);
7408 return FIRST_APPLICATION_UID + N;
7409 }
7410
7411 public PackageSetting getDisabledSystemPkg(String name) {
7412 synchronized(mPackages) {
7413 PackageSetting ps = mDisabledSysPackages.get(name);
7414 return ps;
7415 }
7416 }
7417
7418 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7419 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7420 if (Config.LOGV) {
7421 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7422 + " componentName = " + componentInfo.name);
7423 Log.v(TAG, "enabledComponents: "
7424 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7425 Log.v(TAG, "disabledComponents: "
7426 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7427 }
7428 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7429 || ((componentInfo.enabled
7430 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7431 || (componentInfo.applicationInfo.enabled
7432 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7433 && !packageSettings.disabledComponents.contains(componentInfo.name))
7434 || packageSettings.enabledComponents.contains(componentInfo.name));
7435 }
7436 }
7437}