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