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