blob: d6cd4ef1001a3a686d658be5364493cd4dd162f4 [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
Fred Quintana718d8a22009-04-29 17:53:20 -07001681 /**
1682 * @deprecated
1683 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 public void querySyncProviders(List outNames, List outInfo) {
1685 synchronized (mPackages) {
1686 Iterator<Map.Entry<String, PackageParser.Provider>> i
1687 = mProviders.entrySet().iterator();
1688
1689 while (i.hasNext()) {
1690 Map.Entry<String, PackageParser.Provider> entry = i.next();
1691 PackageParser.Provider p = entry.getValue();
1692
1693 if (p.syncable
1694 && (!mSafeMode || (p.info.applicationInfo.flags
1695 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1696 outNames.add(entry.getKey());
1697 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1698 }
1699 }
1700 }
1701 }
1702
1703 public List<ProviderInfo> queryContentProviders(String processName,
1704 int uid, int flags) {
1705 ArrayList<ProviderInfo> finalList = null;
1706
1707 synchronized (mPackages) {
1708 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1709 while (i.hasNext()) {
1710 PackageParser.Provider p = i.next();
1711 if (p.info.authority != null
1712 && (processName == null ||
1713 (p.info.processName.equals(processName)
1714 && p.info.applicationInfo.uid == uid))
1715 && mSettings.isEnabledLP(p.info, flags)
1716 && (!mSafeMode || (p.info.applicationInfo.flags
1717 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1718 if (finalList == null) {
1719 finalList = new ArrayList<ProviderInfo>(3);
1720 }
1721 finalList.add(PackageParser.generateProviderInfo(p,
1722 flags));
1723 }
1724 }
1725 }
1726
1727 if (finalList != null) {
1728 Collections.sort(finalList, mProviderInitOrderSorter);
1729 }
1730
1731 return finalList;
1732 }
1733
1734 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1735 int flags) {
1736 synchronized (mPackages) {
1737 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1738 return PackageParser.generateInstrumentationInfo(i, flags);
1739 }
1740 }
1741
1742 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1743 int flags) {
1744 ArrayList<InstrumentationInfo> finalList =
1745 new ArrayList<InstrumentationInfo>();
1746
1747 synchronized (mPackages) {
1748 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1749 while (i.hasNext()) {
1750 PackageParser.Instrumentation p = i.next();
1751 if (targetPackage == null
1752 || targetPackage.equals(p.info.targetPackage)) {
1753 finalList.add(PackageParser.generateInstrumentationInfo(p,
1754 flags));
1755 }
1756 }
1757 }
1758
1759 return finalList;
1760 }
1761
1762 private void scanDirLI(File dir, int flags, int scanMode) {
1763 Log.d(TAG, "Scanning app dir " + dir);
1764
1765 String[] files = dir.list();
1766
1767 int i;
1768 for (i=0; i<files.length; i++) {
1769 File file = new File(dir, files[i]);
1770 PackageParser.Package pkg = scanPackageLI(file, file, file,
1771 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1772 }
1773 }
1774
1775 private static void reportSettingsProblem(int priority, String msg) {
1776 try {
1777 File dataDir = Environment.getDataDirectory();
1778 File systemDir = new File(dataDir, "system");
1779 File fname = new File(systemDir, "uiderrors.txt");
1780 FileOutputStream out = new FileOutputStream(fname, true);
1781 PrintWriter pw = new PrintWriter(out);
1782 pw.println(msg);
1783 pw.close();
1784 FileUtils.setPermissions(
1785 fname.toString(),
1786 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1787 -1, -1);
1788 } catch (java.io.IOException e) {
1789 }
1790 Log.println(priority, TAG, msg);
1791 }
1792
1793 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1794 PackageParser.Package pkg, File srcFile, int parseFlags) {
1795 if (GET_CERTIFICATES) {
1796 if (ps == null || !ps.codePath.equals(srcFile)
1797 || ps.getTimeStamp() != srcFile.lastModified()) {
1798 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1799 if (!pp.collectCertificates(pkg, parseFlags)) {
1800 mLastScanError = pp.getParseError();
1801 return false;
1802 }
1803 }
1804 }
1805 return true;
1806 }
1807
1808 /*
1809 * Scan a package and return the newly parsed package.
1810 * Returns null in case of errors and the error code is stored in mLastScanError
1811 */
1812 private PackageParser.Package scanPackageLI(File scanFile,
1813 File destCodeFile, File destResourceFile, int parseFlags,
1814 int scanMode) {
1815 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1816 parseFlags |= mDefParseFlags;
1817 PackageParser pp = new PackageParser(scanFile.getPath());
1818 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07001819 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 final PackageParser.Package pkg = pp.parsePackage(scanFile,
1821 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
1822 if (pkg == null) {
1823 mLastScanError = pp.getParseError();
1824 return null;
1825 }
1826 PackageSetting ps;
1827 PackageSetting updatedPkg;
1828 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001829 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
1831 }
1832 if (updatedPkg != null) {
1833 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
1834 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
1835 }
1836 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1837 // Check for updated system applications here
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07001838 if (updatedPkg != null) {
1839 if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
1840 if (pkg.mVersionCode <= ps.versionCode) {
1841 // The system package has been updated and the code path does not match
1842 // Ignore entry. Just return
1843 Log.w(TAG, "Package:" + pkg.packageName +
1844 " has been updated. Ignoring the one from path:"+scanFile);
1845 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1846 return null;
1847 } else {
1848 // Delete the older apk pointed to by ps
1849 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
1850 mSettings.enableSystemPackageLP(ps.name);
1851 }
1852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 }
1854 }
1855 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
1856 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
1857 return null;
1858 }
1859 // The apk is forward locked (not public) if its code and resources
1860 // are kept in different files.
1861 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
1862 scanMode |= SCAN_FORWARD_LOCKED;
1863 }
1864 // Note that we invoke the following method only if we are about to unpack an application
1865 return scanPackageLI(scanFile, destCodeFile, destResourceFile,
1866 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
1867 }
1868
1869 private static String fixProcessName(String defProcessName,
1870 String processName, int uid) {
1871 if (processName == null) {
1872 return defProcessName;
1873 }
1874 return processName;
1875 }
1876
1877 private boolean verifySignaturesLP(PackageSetting pkgSetting,
1878 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
1879 if (pkg.mSignatures != null) {
1880 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
1881 updateSignature)) {
1882 Log.e(TAG, "Package " + pkg.packageName
1883 + " signatures do not match the previously installed version; ignoring!");
1884 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1885 return false;
1886 }
1887
1888 if (pkgSetting.sharedUser != null) {
1889 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1890 pkg.mSignatures, updateSignature)) {
1891 Log.e(TAG, "Package " + pkg.packageName
1892 + " has no signatures that match those in shared user "
1893 + pkgSetting.sharedUser.name + "; ignoring!");
1894 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
1895 return false;
1896 }
1897 }
1898 } else {
1899 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1900 }
1901 return true;
1902 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001903
1904 public boolean performDexOpt(String packageName) {
1905 if (!mNoDexOpt) {
1906 return false;
1907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001909 PackageParser.Package p;
1910 synchronized (mPackages) {
1911 p = mPackages.get(packageName);
1912 if (p == null || p.mDidDexOpt) {
1913 return false;
1914 }
1915 }
1916 synchronized (mInstallLock) {
1917 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
1918 }
1919 }
1920
1921 static final int DEX_OPT_SKIPPED = 0;
1922 static final int DEX_OPT_PERFORMED = 1;
1923 static final int DEX_OPT_FAILED = -1;
1924
1925 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
1926 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07001927 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001928 String path = pkg.mScanPath;
1929 int ret = 0;
1930 try {
1931 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
1932 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
1933 !pkg.mForwardLocked);
1934 pkg.mDidDexOpt = true;
1935 performed = true;
1936 }
1937 } catch (FileNotFoundException e) {
1938 Log.w(TAG, "Apk not found for dexopt: " + path);
1939 ret = -1;
1940 } catch (IOException e) {
1941 Log.w(TAG, "Exception reading apk: " + path, e);
1942 ret = -1;
1943 }
1944 if (ret < 0) {
1945 //error from installer
1946 return DEX_OPT_FAILED;
1947 }
1948 }
1949
1950 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
1951 }
1952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 private PackageParser.Package scanPackageLI(
1954 File scanFile, File destCodeFile, File destResourceFile,
1955 PackageParser.Package pkg, int parseFlags, int scanMode) {
1956
1957 mScanningPath = scanFile;
1958 if (pkg == null) {
1959 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1960 return null;
1961 }
1962
1963 final String pkgName = pkg.applicationInfo.packageName;
1964 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1965 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
1966 }
1967
1968 if (pkgName.equals("android")) {
1969 synchronized (mPackages) {
1970 if (mAndroidApplication != null) {
1971 Log.w(TAG, "*************************************************");
1972 Log.w(TAG, "Core android package being redefined. Skipping.");
1973 Log.w(TAG, " file=" + mScanningPath);
1974 Log.w(TAG, "*************************************************");
1975 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1976 return null;
1977 }
1978
1979 // Set up information for our fall-back user intent resolution
1980 // activity.
1981 mPlatformPackage = pkg;
1982 pkg.mVersionCode = mSdkVersion;
1983 mAndroidApplication = pkg.applicationInfo;
1984 mResolveActivity.applicationInfo = mAndroidApplication;
1985 mResolveActivity.name = ResolverActivity.class.getName();
1986 mResolveActivity.packageName = mAndroidApplication.packageName;
1987 mResolveActivity.processName = mAndroidApplication.processName;
1988 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1989 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
1990 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
1991 mResolveActivity.exported = true;
1992 mResolveActivity.enabled = true;
1993 mResolveInfo.activityInfo = mResolveActivity;
1994 mResolveInfo.priority = 0;
1995 mResolveInfo.preferredOrder = 0;
1996 mResolveInfo.match = 0;
1997 mResolveComponentName = new ComponentName(
1998 mAndroidApplication.packageName, mResolveActivity.name);
1999 }
2000 }
2001
2002 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2003 TAG, "Scanning package " + pkgName);
2004 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2005 Log.w(TAG, "*************************************************");
2006 Log.w(TAG, "Application package " + pkgName
2007 + " already installed. Skipping duplicate.");
2008 Log.w(TAG, "*************************************************");
2009 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2010 return null;
2011 }
2012
2013 SharedUserSetting suid = null;
2014 PackageSetting pkgSetting = null;
2015
2016 boolean removeExisting = false;
2017
2018 synchronized (mPackages) {
2019 // Check all shared libraries and map to their actual file path.
2020 if (pkg.usesLibraryFiles != null) {
2021 for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
2022 String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
2023 if (file == null) {
2024 Log.e(TAG, "Package " + pkg.packageName
2025 + " requires unavailable shared library "
2026 + pkg.usesLibraryFiles[i] + "; ignoring!");
2027 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2028 return null;
2029 }
2030 pkg.usesLibraryFiles[i] = file;
2031 }
2032 }
2033
2034 if (pkg.mSharedUserId != null) {
2035 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2036 pkg.applicationInfo.flags, true);
2037 if (suid == null) {
2038 Log.w(TAG, "Creating application package " + pkgName
2039 + " for shared user failed");
2040 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2041 return null;
2042 }
2043 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2044 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2045 + suid.userId + "): packages=" + suid.packages);
2046 }
2047 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002048
2049 // Just create the setting, don't add it yet. For already existing packages
2050 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2052 destResourceFile, pkg.applicationInfo.flags, true, false);
2053 if (pkgSetting == null) {
2054 Log.w(TAG, "Creating application package " + pkgName + " failed");
2055 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2056 return null;
2057 }
2058 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2059 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2060 }
2061
2062 pkg.applicationInfo.uid = pkgSetting.userId;
2063 pkg.mExtras = pkgSetting;
2064
2065 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
2066 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2067 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2068 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2069 return null;
2070 }
2071 // The signature has changed, but this package is in the system
2072 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002073 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 // However... if this package is part of a shared user, but it
2075 // doesn't match the signature of the shared user, let's fail.
2076 // What this means is that you can't change the signatures
2077 // associated with an overall shared user, which doesn't seem all
2078 // that unreasonable.
2079 if (pkgSetting.sharedUser != null) {
2080 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2081 pkg.mSignatures, false)) {
2082 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2083 return null;
2084 }
2085 }
2086 removeExisting = true;
2087 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002088
2089 // Verify that this new package doesn't have any content providers
2090 // that conflict with existing packages. Only do this if the
2091 // package isn't already installed, since we don't want to break
2092 // things that are installed.
2093 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2094 int N = pkg.providers.size();
2095 int i;
2096 for (i=0; i<N; i++) {
2097 PackageParser.Provider p = pkg.providers.get(i);
2098 String names[] = p.info.authority.split(";");
2099 for (int j = 0; j < names.length; j++) {
2100 if (mProviders.containsKey(names[j])) {
2101 PackageParser.Provider other = mProviders.get(names[j]);
2102 Log.w(TAG, "Can't install because provider name " + names[j] +
2103 " (in package " + pkg.applicationInfo.packageName +
2104 ") is already used by "
2105 + ((other != null && other.component != null)
2106 ? other.component.getPackageName() : "?"));
2107 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2108 return null;
2109 }
2110 }
2111 }
2112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 }
2114
2115 if (removeExisting) {
2116 if (mInstaller != null) {
2117 int ret = mInstaller.remove(pkgName);
2118 if (ret != 0) {
2119 String msg = "System package " + pkg.packageName
2120 + " could not have data directory erased after signature change.";
2121 reportSettingsProblem(Log.WARN, msg);
2122 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2123 return null;
2124 }
2125 }
2126 Log.w(TAG, "System package " + pkg.packageName
2127 + " signature changed: existing data removed.");
2128 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2129 }
2130
2131 long scanFileTime = scanFile.lastModified();
2132 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2133 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2134 pkg.applicationInfo.processName = fixProcessName(
2135 pkg.applicationInfo.packageName,
2136 pkg.applicationInfo.processName,
2137 pkg.applicationInfo.uid);
2138 pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
2139
2140 File dataPath;
2141 if (mPlatformPackage == pkg) {
2142 // The system package is special.
2143 dataPath = new File (Environment.getDataDirectory(), "system");
2144 pkg.applicationInfo.dataDir = dataPath.getPath();
2145 } else {
2146 // This is a normal package, need to make its data directory.
2147 dataPath = new File(mAppDataDir, pkgName);
2148 if (dataPath.exists()) {
2149 mOutPermissions[1] = 0;
2150 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2151 if (mOutPermissions[1] == pkg.applicationInfo.uid
2152 || !Process.supportsProcesses()) {
2153 pkg.applicationInfo.dataDir = dataPath.getPath();
2154 } else {
2155 boolean recovered = false;
2156 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2157 // If this is a system app, we can at least delete its
2158 // current data so the application will still work.
2159 if (mInstaller != null) {
2160 int ret = mInstaller.remove(pkgName);
2161 if(ret >= 0) {
2162 // Old data gone!
2163 String msg = "System package " + pkg.packageName
2164 + " has changed from uid: "
2165 + mOutPermissions[1] + " to "
2166 + pkg.applicationInfo.uid + "; old data erased";
2167 reportSettingsProblem(Log.WARN, msg);
2168 recovered = true;
2169
2170 // And now re-install the app.
2171 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2172 pkg.applicationInfo.uid);
2173 if (ret == -1) {
2174 // Ack should not happen!
2175 msg = "System package " + pkg.packageName
2176 + " could not have data directory re-created after delete.";
2177 reportSettingsProblem(Log.WARN, msg);
2178 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2179 return null;
2180 }
2181 }
2182 }
2183 if (!recovered) {
2184 mHasSystemUidErrors = true;
2185 }
2186 }
2187 if (!recovered) {
2188 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2189 + pkg.applicationInfo.uid + "/fs_"
2190 + mOutPermissions[1];
2191 String msg = "Package " + pkg.packageName
2192 + " has mismatched uid: "
2193 + mOutPermissions[1] + " on disk, "
2194 + pkg.applicationInfo.uid + " in settings";
2195 synchronized (mPackages) {
2196 if (!mReportedUidError) {
2197 mReportedUidError = true;
2198 msg = msg + "; read messages:\n"
2199 + mSettings.getReadMessagesLP();
2200 }
2201 reportSettingsProblem(Log.ERROR, msg);
2202 }
2203 }
2204 }
2205 pkg.applicationInfo.dataDir = dataPath.getPath();
2206 } else {
2207 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2208 Log.v(TAG, "Want this data dir: " + dataPath);
2209 //invoke installer to do the actual installation
2210 if (mInstaller != null) {
2211 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2212 pkg.applicationInfo.uid);
2213 if(ret < 0) {
2214 // Error from installer
2215 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2216 return null;
2217 }
2218 } else {
2219 dataPath.mkdirs();
2220 if (dataPath.exists()) {
2221 FileUtils.setPermissions(
2222 dataPath.toString(),
2223 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2224 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2225 }
2226 }
2227 if (dataPath.exists()) {
2228 pkg.applicationInfo.dataDir = dataPath.getPath();
2229 } else {
2230 Log.w(TAG, "Unable to create data directory: " + dataPath);
2231 pkg.applicationInfo.dataDir = null;
2232 }
2233 }
2234 }
2235
2236 // Perform shared library installation and dex validation and
2237 // optimization, if this is not a system app.
2238 if (mInstaller != null) {
2239 String path = scanFile.getPath();
2240 if (scanFileNewer) {
2241 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002242 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2243 if (err != PackageManager.INSTALL_SUCCEEDED) {
2244 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 return null;
2246 }
2247 }
2248
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002249 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2250 pkg.mScanPath = path;
2251
2252 if ((scanMode&SCAN_NO_DEX) == 0) {
2253 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2255 return null;
2256 }
2257 }
2258 }
2259
2260 if (mFactoryTest && pkg.requestedPermissions.contains(
2261 android.Manifest.permission.FACTORY_TEST)) {
2262 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2263 }
2264
2265 if ((scanMode&SCAN_MONITOR) != 0) {
2266 pkg.mPath = destCodeFile.getAbsolutePath();
2267 mAppDirs.put(pkg.mPath, pkg);
2268 }
2269
2270 synchronized (mPackages) {
2271 // We don't expect installation to fail beyond this point
2272 // Add the new setting to mSettings
2273 mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
2274 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002275 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 int N = pkg.providers.size();
2277 StringBuilder r = null;
2278 int i;
2279 for (i=0; i<N; i++) {
2280 PackageParser.Provider p = pkg.providers.get(i);
2281 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2282 p.info.processName, pkg.applicationInfo.uid);
2283 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2284 p.info.name), p);
2285 p.syncable = p.info.isSyncable;
2286 String names[] = p.info.authority.split(";");
2287 p.info.authority = null;
2288 for (int j = 0; j < names.length; j++) {
2289 if (j == 1 && p.syncable) {
2290 // We only want the first authority for a provider to possibly be
2291 // syncable, so if we already added this provider using a different
2292 // authority clear the syncable flag. We copy the provider before
2293 // changing it because the mProviders object contains a reference
2294 // to a provider that we don't want to change.
2295 // Only do this for the second authority since the resulting provider
2296 // object can be the same for all future authorities for this provider.
2297 p = new PackageParser.Provider(p);
2298 p.syncable = false;
2299 }
2300 if (!mProviders.containsKey(names[j])) {
2301 mProviders.put(names[j], p);
2302 if (p.info.authority == null) {
2303 p.info.authority = names[j];
2304 } else {
2305 p.info.authority = p.info.authority + ";" + names[j];
2306 }
2307 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2308 Log.d(TAG, "Registered content provider: " + names[j] +
2309 ", className = " + p.info.name +
2310 ", isSyncable = " + p.info.isSyncable);
2311 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002312 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 Log.w(TAG, "Skipping provider name " + names[j] +
2314 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002315 "): name already used by "
2316 + ((other != null && other.component != null)
2317 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 }
2319 }
2320 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2321 if (r == null) {
2322 r = new StringBuilder(256);
2323 } else {
2324 r.append(' ');
2325 }
2326 r.append(p.info.name);
2327 }
2328 }
2329 if (r != null) {
2330 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2331 }
2332
2333 N = pkg.services.size();
2334 r = null;
2335 for (i=0; i<N; i++) {
2336 PackageParser.Service s = pkg.services.get(i);
2337 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2338 s.info.processName, pkg.applicationInfo.uid);
2339 mServices.addService(s);
2340 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2341 if (r == null) {
2342 r = new StringBuilder(256);
2343 } else {
2344 r.append(' ');
2345 }
2346 r.append(s.info.name);
2347 }
2348 }
2349 if (r != null) {
2350 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2351 }
2352
2353 N = pkg.receivers.size();
2354 r = null;
2355 for (i=0; i<N; i++) {
2356 PackageParser.Activity a = pkg.receivers.get(i);
2357 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2358 a.info.processName, pkg.applicationInfo.uid);
2359 mReceivers.addActivity(a, "receiver");
2360 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2361 if (r == null) {
2362 r = new StringBuilder(256);
2363 } else {
2364 r.append(' ');
2365 }
2366 r.append(a.info.name);
2367 }
2368 }
2369 if (r != null) {
2370 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2371 }
2372
2373 N = pkg.activities.size();
2374 r = null;
2375 for (i=0; i<N; i++) {
2376 PackageParser.Activity a = pkg.activities.get(i);
2377 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2378 a.info.processName, pkg.applicationInfo.uid);
2379 mActivities.addActivity(a, "activity");
2380 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2381 if (r == null) {
2382 r = new StringBuilder(256);
2383 } else {
2384 r.append(' ');
2385 }
2386 r.append(a.info.name);
2387 }
2388 }
2389 if (r != null) {
2390 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2391 }
2392
2393 N = pkg.permissionGroups.size();
2394 r = null;
2395 for (i=0; i<N; i++) {
2396 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2397 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2398 if (cur == null) {
2399 mPermissionGroups.put(pg.info.name, pg);
2400 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2401 if (r == null) {
2402 r = new StringBuilder(256);
2403 } else {
2404 r.append(' ');
2405 }
2406 r.append(pg.info.name);
2407 }
2408 } else {
2409 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2410 + pg.info.packageName + " ignored: original from "
2411 + cur.info.packageName);
2412 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2413 if (r == null) {
2414 r = new StringBuilder(256);
2415 } else {
2416 r.append(' ');
2417 }
2418 r.append("DUP:");
2419 r.append(pg.info.name);
2420 }
2421 }
2422 }
2423 if (r != null) {
2424 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2425 }
2426
2427 N = pkg.permissions.size();
2428 r = null;
2429 for (i=0; i<N; i++) {
2430 PackageParser.Permission p = pkg.permissions.get(i);
2431 HashMap<String, BasePermission> permissionMap =
2432 p.tree ? mSettings.mPermissionTrees
2433 : mSettings.mPermissions;
2434 p.group = mPermissionGroups.get(p.info.group);
2435 if (p.info.group == null || p.group != null) {
2436 BasePermission bp = permissionMap.get(p.info.name);
2437 if (bp == null) {
2438 bp = new BasePermission(p.info.name, p.info.packageName,
2439 BasePermission.TYPE_NORMAL);
2440 permissionMap.put(p.info.name, bp);
2441 }
2442 if (bp.perm == null) {
2443 if (bp.sourcePackage == null
2444 || bp.sourcePackage.equals(p.info.packageName)) {
2445 BasePermission tree = findPermissionTreeLP(p.info.name);
2446 if (tree == null
2447 || tree.sourcePackage.equals(p.info.packageName)) {
2448 bp.perm = p;
2449 bp.uid = pkg.applicationInfo.uid;
2450 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2451 if (r == null) {
2452 r = new StringBuilder(256);
2453 } else {
2454 r.append(' ');
2455 }
2456 r.append(p.info.name);
2457 }
2458 } else {
2459 Log.w(TAG, "Permission " + p.info.name + " from package "
2460 + p.info.packageName + " ignored: base tree "
2461 + tree.name + " is from package "
2462 + tree.sourcePackage);
2463 }
2464 } else {
2465 Log.w(TAG, "Permission " + p.info.name + " from package "
2466 + p.info.packageName + " ignored: original from "
2467 + bp.sourcePackage);
2468 }
2469 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2470 if (r == null) {
2471 r = new StringBuilder(256);
2472 } else {
2473 r.append(' ');
2474 }
2475 r.append("DUP:");
2476 r.append(p.info.name);
2477 }
2478 } else {
2479 Log.w(TAG, "Permission " + p.info.name + " from package "
2480 + p.info.packageName + " ignored: no group "
2481 + p.group);
2482 }
2483 }
2484 if (r != null) {
2485 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2486 }
2487
2488 N = pkg.instrumentation.size();
2489 r = null;
2490 for (i=0; i<N; i++) {
2491 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2492 a.info.packageName = pkg.applicationInfo.packageName;
2493 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2494 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2495 a.info.dataDir = pkg.applicationInfo.dataDir;
2496 mInstrumentation.put(a.component, a);
2497 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2498 if (r == null) {
2499 r = new StringBuilder(256);
2500 } else {
2501 r.append(' ');
2502 }
2503 r.append(a.info.name);
2504 }
2505 }
2506 if (r != null) {
2507 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2508 }
2509
Dianne Hackborn854060af2009-07-09 18:14:31 -07002510 if (pkg.protectedBroadcasts != null) {
2511 N = pkg.protectedBroadcasts.size();
2512 for (i=0; i<N; i++) {
2513 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2514 }
2515 }
2516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 pkgSetting.setTimeStamp(scanFileTime);
2518 }
2519
2520 return pkg;
2521 }
2522
Dianne Hackbornb1811182009-05-21 15:45:42 -07002523 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2524 File dataPath, File scanFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002526 final String sharedLibraryABI = Build.CPU_ABI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2528 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2529 final String sharedLibrarySuffix = ".so";
Dianne Hackbornb1811182009-05-21 15:45:42 -07002530 boolean hasNativeCode = false;
2531 boolean installedNativeCode = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 try {
2533 ZipFile zipFile = new ZipFile(scanFile);
2534 Enumeration<ZipEntry> entries =
2535 (Enumeration<ZipEntry>) zipFile.entries();
2536
2537 while (entries.hasMoreElements()) {
2538 ZipEntry entry = entries.nextElement();
2539 if (entry.isDirectory()) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002540 if (!hasNativeCode && entry.getName().startsWith("lib")) {
2541 hasNativeCode = true;
2542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 continue;
2544 }
2545 String entryName = entry.getName();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002546 if (entryName.startsWith("lib/")) {
2547 hasNativeCode = true;
2548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2550 && entryName.endsWith(sharedLibrarySuffix))) {
2551 continue;
2552 }
2553 String libFileName = entryName.substring(
2554 apkLibraryDirectory.length());
2555 if (libFileName.contains("/")
2556 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2557 continue;
2558 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002559
2560 installedNativeCode = true;
2561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2563 File.separator + libFileName;
2564 File sharedLibraryFile = new File(sharedLibraryFilePath);
2565 if (! sharedLibraryFile.exists() ||
2566 sharedLibraryFile.length() != entry.getSize() ||
2567 sharedLibraryFile.lastModified() != entry.getTime()) {
2568 if (Config.LOGD) {
2569 Log.d(TAG, "Caching shared lib " + entry.getName());
2570 }
2571 if (mInstaller == null) {
2572 sharedLibraryDir.mkdir();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 }
2574 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2575 sharedLibraryFile);
2576 }
2577 }
2578 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002579 Log.w(TAG, "Failed to cache package shared libs", e);
2580 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002582
2583 if (hasNativeCode && !installedNativeCode) {
2584 Log.w(TAG, "Install failed: .apk has native code but none for arch "
2585 + Build.CPU_ABI);
2586 return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
2587 }
2588
2589 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 }
2591
2592 private void cacheSharedLibLI(PackageParser.Package pkg,
2593 ZipFile zipFile, ZipEntry entry,
2594 File sharedLibraryDir,
2595 File sharedLibraryFile) throws IOException {
2596 InputStream inputStream = zipFile.getInputStream(entry);
2597 try {
2598 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2599 String tempFilePath = tempFile.getPath();
2600 // XXX package manager can't change owner, so the lib files for
2601 // now need to be left as world readable and owned by the system.
2602 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2603 ! tempFile.setLastModified(entry.getTime()) ||
2604 FileUtils.setPermissions(tempFilePath,
2605 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2606 |FileUtils.S_IROTH, -1, -1) != 0 ||
2607 ! tempFile.renameTo(sharedLibraryFile)) {
2608 // Failed to properly write file.
2609 tempFile.delete();
2610 throw new IOException("Couldn't create cached shared lib "
2611 + sharedLibraryFile + " in " + sharedLibraryDir);
2612 }
2613 } finally {
2614 inputStream.close();
2615 }
2616 }
2617
2618 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2619 if (chatty && Config.LOGD) Log.d(
2620 TAG, "Removing package " + pkg.applicationInfo.packageName );
2621
2622 synchronized (mPackages) {
2623 if (pkg.mPreferredOrder > 0) {
2624 mSettings.mPreferredPackages.remove(pkg);
2625 pkg.mPreferredOrder = 0;
2626 updatePreferredIndicesLP();
2627 }
2628
2629 clearPackagePreferredActivitiesLP(pkg.packageName);
2630
2631 mPackages.remove(pkg.applicationInfo.packageName);
2632 if (pkg.mPath != null) {
2633 mAppDirs.remove(pkg.mPath);
2634 }
2635
2636 PackageSetting ps = (PackageSetting)pkg.mExtras;
2637 if (ps != null && ps.sharedUser != null) {
2638 // XXX don't do this until the data is removed.
2639 if (false) {
2640 ps.sharedUser.packages.remove(ps);
2641 if (ps.sharedUser.packages.size() == 0) {
2642 // Remove.
2643 }
2644 }
2645 }
2646
2647 int N = pkg.providers.size();
2648 StringBuilder r = null;
2649 int i;
2650 for (i=0; i<N; i++) {
2651 PackageParser.Provider p = pkg.providers.get(i);
2652 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2653 p.info.name));
2654 if (p.info.authority == null) {
2655
2656 /* The is another ContentProvider with this authority when
2657 * this app was installed so this authority is null,
2658 * Ignore it as we don't have to unregister the provider.
2659 */
2660 continue;
2661 }
2662 String names[] = p.info.authority.split(";");
2663 for (int j = 0; j < names.length; j++) {
2664 if (mProviders.get(names[j]) == p) {
2665 mProviders.remove(names[j]);
2666 if (chatty && Config.LOGD) Log.d(
2667 TAG, "Unregistered content provider: " + names[j] +
2668 ", className = " + p.info.name +
2669 ", isSyncable = " + p.info.isSyncable);
2670 }
2671 }
2672 if (chatty) {
2673 if (r == null) {
2674 r = new StringBuilder(256);
2675 } else {
2676 r.append(' ');
2677 }
2678 r.append(p.info.name);
2679 }
2680 }
2681 if (r != null) {
2682 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2683 }
2684
2685 N = pkg.services.size();
2686 r = null;
2687 for (i=0; i<N; i++) {
2688 PackageParser.Service s = pkg.services.get(i);
2689 mServices.removeService(s);
2690 if (chatty) {
2691 if (r == null) {
2692 r = new StringBuilder(256);
2693 } else {
2694 r.append(' ');
2695 }
2696 r.append(s.info.name);
2697 }
2698 }
2699 if (r != null) {
2700 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2701 }
2702
2703 N = pkg.receivers.size();
2704 r = null;
2705 for (i=0; i<N; i++) {
2706 PackageParser.Activity a = pkg.receivers.get(i);
2707 mReceivers.removeActivity(a, "receiver");
2708 if (chatty) {
2709 if (r == null) {
2710 r = new StringBuilder(256);
2711 } else {
2712 r.append(' ');
2713 }
2714 r.append(a.info.name);
2715 }
2716 }
2717 if (r != null) {
2718 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2719 }
2720
2721 N = pkg.activities.size();
2722 r = null;
2723 for (i=0; i<N; i++) {
2724 PackageParser.Activity a = pkg.activities.get(i);
2725 mActivities.removeActivity(a, "activity");
2726 if (chatty) {
2727 if (r == null) {
2728 r = new StringBuilder(256);
2729 } else {
2730 r.append(' ');
2731 }
2732 r.append(a.info.name);
2733 }
2734 }
2735 if (r != null) {
2736 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2737 }
2738
2739 N = pkg.permissions.size();
2740 r = null;
2741 for (i=0; i<N; i++) {
2742 PackageParser.Permission p = pkg.permissions.get(i);
2743 boolean tree = false;
2744 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2745 if (bp == null) {
2746 tree = true;
2747 bp = mSettings.mPermissionTrees.get(p.info.name);
2748 }
2749 if (bp != null && bp.perm == p) {
2750 if (bp.type != BasePermission.TYPE_BUILTIN) {
2751 if (tree) {
2752 mSettings.mPermissionTrees.remove(p.info.name);
2753 } else {
2754 mSettings.mPermissions.remove(p.info.name);
2755 }
2756 } else {
2757 bp.perm = null;
2758 }
2759 if (chatty) {
2760 if (r == null) {
2761 r = new StringBuilder(256);
2762 } else {
2763 r.append(' ');
2764 }
2765 r.append(p.info.name);
2766 }
2767 }
2768 }
2769 if (r != null) {
2770 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2771 }
2772
2773 N = pkg.instrumentation.size();
2774 r = null;
2775 for (i=0; i<N; i++) {
2776 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2777 mInstrumentation.remove(a.component);
2778 if (chatty) {
2779 if (r == null) {
2780 r = new StringBuilder(256);
2781 } else {
2782 r.append(' ');
2783 }
2784 r.append(a.info.name);
2785 }
2786 }
2787 if (r != null) {
2788 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2789 }
2790 }
2791 }
2792
2793 private static final boolean isPackageFilename(String name) {
2794 return name != null && name.endsWith(".apk");
2795 }
2796
2797 private void updatePermissionsLP() {
2798 // Make sure there are no dangling permission trees.
2799 Iterator<BasePermission> it = mSettings.mPermissionTrees
2800 .values().iterator();
2801 while (it.hasNext()) {
2802 BasePermission bp = it.next();
2803 if (bp.perm == null) {
2804 Log.w(TAG, "Removing dangling permission tree: " + bp.name
2805 + " from package " + bp.sourcePackage);
2806 it.remove();
2807 }
2808 }
2809
2810 // Make sure all dynamic permissions have been assigned to a package,
2811 // and make sure there are no dangling permissions.
2812 it = mSettings.mPermissions.values().iterator();
2813 while (it.hasNext()) {
2814 BasePermission bp = it.next();
2815 if (bp.type == BasePermission.TYPE_DYNAMIC) {
2816 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
2817 + bp.name + " pkg=" + bp.sourcePackage
2818 + " info=" + bp.pendingInfo);
2819 if (bp.perm == null && bp.pendingInfo != null) {
2820 BasePermission tree = findPermissionTreeLP(bp.name);
2821 if (tree != null) {
2822 bp.perm = new PackageParser.Permission(tree.perm.owner,
2823 new PermissionInfo(bp.pendingInfo));
2824 bp.perm.info.packageName = tree.perm.info.packageName;
2825 bp.perm.info.name = bp.name;
2826 bp.uid = tree.uid;
2827 }
2828 }
2829 }
2830 if (bp.perm == null) {
2831 Log.w(TAG, "Removing dangling permission: " + bp.name
2832 + " from package " + bp.sourcePackage);
2833 it.remove();
2834 }
2835 }
2836
2837 // Now update the permissions for all packages, in particular
2838 // replace the granted permissions of the system packages.
2839 for (PackageParser.Package pkg : mPackages.values()) {
2840 grantPermissionsLP(pkg, false);
2841 }
2842 }
2843
2844 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
2845 final PackageSetting ps = (PackageSetting)pkg.mExtras;
2846 if (ps == null) {
2847 return;
2848 }
2849 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2850 boolean addedPermission = false;
2851
2852 if (replace) {
2853 ps.permissionsFixed = false;
2854 if (gp == ps) {
2855 gp.grantedPermissions.clear();
2856 gp.gids = mGlobalGids;
2857 }
2858 }
2859
2860 if (gp.gids == null) {
2861 gp.gids = mGlobalGids;
2862 }
2863
2864 final int N = pkg.requestedPermissions.size();
2865 for (int i=0; i<N; i++) {
2866 String name = pkg.requestedPermissions.get(i);
2867 BasePermission bp = mSettings.mPermissions.get(name);
2868 PackageParser.Permission p = bp != null ? bp.perm : null;
2869 if (false) {
2870 if (gp != ps) {
2871 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
2872 + ": " + p);
2873 }
2874 }
2875 if (p != null) {
2876 final String perm = p.info.name;
2877 boolean allowed;
2878 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
2879 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
2880 allowed = true;
2881 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
2882 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2883 allowed = (checkSignaturesLP(p.owner, pkg)
2884 == PackageManager.SIGNATURE_MATCH)
2885 || (checkSignaturesLP(mPlatformPackage, pkg)
2886 == PackageManager.SIGNATURE_MATCH);
2887 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2888 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
2889 // For updated system applications, the signatureOrSystem permission
2890 // is granted only if it had been defined by the original application.
2891 if ((pkg.applicationInfo.flags
2892 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
2893 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
2894 if(sysPs.grantedPermissions.contains(perm)) {
2895 allowed = true;
2896 } else {
2897 allowed = false;
2898 }
2899 } else {
2900 allowed = true;
2901 }
2902 }
2903 }
2904 } else {
2905 allowed = false;
2906 }
2907 if (false) {
2908 if (gp != ps) {
2909 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
2910 }
2911 }
2912 if (allowed) {
2913 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
2914 && ps.permissionsFixed) {
2915 // If this is an existing, non-system package, then
2916 // we can't add any new permissions to it.
2917 if (!gp.loadedPermissions.contains(perm)) {
2918 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07002919 // Except... if this is a permission that was added
2920 // to the platform (note: need to only do this when
2921 // updating the platform).
2922 final int NP = PackageParser.NEW_PERMISSIONS.length;
2923 for (int ip=0; ip<NP; ip++) {
2924 final PackageParser.NewPermissionInfo npi
2925 = PackageParser.NEW_PERMISSIONS[ip];
2926 if (npi.name.equals(perm)
2927 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
2928 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07002929 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07002930 + pkg.packageName);
2931 break;
2932 }
2933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 }
2935 }
2936 if (allowed) {
2937 if (!gp.grantedPermissions.contains(perm)) {
2938 addedPermission = true;
2939 gp.grantedPermissions.add(perm);
2940 gp.gids = appendInts(gp.gids, bp.gids);
2941 }
2942 } else {
2943 Log.w(TAG, "Not granting permission " + perm
2944 + " to package " + pkg.packageName
2945 + " because it was previously installed without");
2946 }
2947 } else {
2948 Log.w(TAG, "Not granting permission " + perm
2949 + " to package " + pkg.packageName
2950 + " (protectionLevel=" + p.info.protectionLevel
2951 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
2952 + ")");
2953 }
2954 } else {
2955 Log.w(TAG, "Unknown permission " + name
2956 + " in package " + pkg.packageName);
2957 }
2958 }
2959
2960 if ((addedPermission || replace) && !ps.permissionsFixed &&
2961 (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2962 // This is the first that we have heard about this package, so the
2963 // permissions we have now selected are fixed until explicitly
2964 // changed.
2965 ps.permissionsFixed = true;
2966 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
2967 }
2968 }
2969
2970 private final class ActivityIntentResolver
2971 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02002972 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02002974 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 }
2976
Mihai Preda074edef2009-05-18 17:13:31 +02002977 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02002979 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2981 }
2982
Mihai Predaeae850c2009-05-13 10:13:48 +02002983 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
2984 ArrayList<PackageParser.Activity> packageActivities) {
2985 if (packageActivities == null) {
2986 return null;
2987 }
2988 mFlags = flags;
2989 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
2990 int N = packageActivities.size();
2991 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
2992 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02002993
2994 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02002995 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02002996 intentFilters = packageActivities.get(i).intents;
2997 if (intentFilters != null && intentFilters.size() > 0) {
2998 listCut.add(intentFilters);
2999 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003000 }
3001 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3002 }
3003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 public final void addActivity(PackageParser.Activity a, String type) {
3005 mActivities.put(a.component, a);
3006 if (SHOW_INFO || Config.LOGV) Log.v(
3007 TAG, " " + type + " " +
3008 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3009 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3010 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003011 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3013 if (SHOW_INFO || Config.LOGV) {
3014 Log.v(TAG, " IntentFilter:");
3015 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3016 }
3017 if (!intent.debugCheck()) {
3018 Log.w(TAG, "==> For Activity " + a.info.name);
3019 }
3020 addFilter(intent);
3021 }
3022 }
3023
3024 public final void removeActivity(PackageParser.Activity a, String type) {
3025 mActivities.remove(a.component);
3026 if (SHOW_INFO || Config.LOGV) Log.v(
3027 TAG, " " + type + " " +
3028 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3029 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3030 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003031 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3033 if (SHOW_INFO || Config.LOGV) {
3034 Log.v(TAG, " IntentFilter:");
3035 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3036 }
3037 removeFilter(intent);
3038 }
3039 }
3040
3041 @Override
3042 protected boolean allowFilterResult(
3043 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3044 ActivityInfo filterAi = filter.activity.info;
3045 for (int i=dest.size()-1; i>=0; i--) {
3046 ActivityInfo destAi = dest.get(i).activityInfo;
3047 if (destAi.name == filterAi.name
3048 && destAi.packageName == filterAi.packageName) {
3049 return false;
3050 }
3051 }
3052 return true;
3053 }
3054
3055 @Override
3056 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3057 int match) {
3058 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3059 return null;
3060 }
3061 final PackageParser.Activity activity = info.activity;
3062 if (mSafeMode && (activity.info.applicationInfo.flags
3063 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3064 return null;
3065 }
3066 final ResolveInfo res = new ResolveInfo();
3067 res.activityInfo = PackageParser.generateActivityInfo(activity,
3068 mFlags);
3069 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3070 res.filter = info;
3071 }
3072 res.priority = info.getPriority();
3073 res.preferredOrder = activity.owner.mPreferredOrder;
3074 //System.out.println("Result: " + res.activityInfo.className +
3075 // " = " + res.priority);
3076 res.match = match;
3077 res.isDefault = info.hasDefault;
3078 res.labelRes = info.labelRes;
3079 res.nonLocalizedLabel = info.nonLocalizedLabel;
3080 res.icon = info.icon;
3081 return res;
3082 }
3083
3084 @Override
3085 protected void sortResults(List<ResolveInfo> results) {
3086 Collections.sort(results, mResolvePrioritySorter);
3087 }
3088
3089 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003090 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003092 out.print(prefix); out.print(
3093 Integer.toHexString(System.identityHashCode(filter.activity)));
3094 out.print(' ');
3095 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 }
3097
3098// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3099// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3100// final List<ResolveInfo> retList = Lists.newArrayList();
3101// while (i.hasNext()) {
3102// final ResolveInfo resolveInfo = i.next();
3103// if (isEnabledLP(resolveInfo.activityInfo)) {
3104// retList.add(resolveInfo);
3105// }
3106// }
3107// return retList;
3108// }
3109
3110 // Keys are String (activity class name), values are Activity.
3111 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3112 = new HashMap<ComponentName, PackageParser.Activity>();
3113 private int mFlags;
3114 }
3115
3116 private final class ServiceIntentResolver
3117 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003118 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003120 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 }
3122
Mihai Preda074edef2009-05-18 17:13:31 +02003123 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003125 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3127 }
3128
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003129 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3130 ArrayList<PackageParser.Service> packageServices) {
3131 if (packageServices == null) {
3132 return null;
3133 }
3134 mFlags = flags;
3135 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3136 int N = packageServices.size();
3137 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3138 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3139
3140 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3141 for (int i = 0; i < N; ++i) {
3142 intentFilters = packageServices.get(i).intents;
3143 if (intentFilters != null && intentFilters.size() > 0) {
3144 listCut.add(intentFilters);
3145 }
3146 }
3147 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3148 }
3149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 public final void addService(PackageParser.Service s) {
3151 mServices.put(s.component, s);
3152 if (SHOW_INFO || Config.LOGV) Log.v(
3153 TAG, " " + (s.info.nonLocalizedLabel != null
3154 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3155 if (SHOW_INFO || Config.LOGV) Log.v(
3156 TAG, " Class=" + s.info.name);
3157 int NI = s.intents.size();
3158 int j;
3159 for (j=0; j<NI; j++) {
3160 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3161 if (SHOW_INFO || Config.LOGV) {
3162 Log.v(TAG, " IntentFilter:");
3163 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3164 }
3165 if (!intent.debugCheck()) {
3166 Log.w(TAG, "==> For Service " + s.info.name);
3167 }
3168 addFilter(intent);
3169 }
3170 }
3171
3172 public final void removeService(PackageParser.Service s) {
3173 mServices.remove(s.component);
3174 if (SHOW_INFO || Config.LOGV) Log.v(
3175 TAG, " " + (s.info.nonLocalizedLabel != null
3176 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3177 if (SHOW_INFO || Config.LOGV) Log.v(
3178 TAG, " Class=" + s.info.name);
3179 int NI = s.intents.size();
3180 int j;
3181 for (j=0; j<NI; j++) {
3182 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3183 if (SHOW_INFO || Config.LOGV) {
3184 Log.v(TAG, " IntentFilter:");
3185 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3186 }
3187 removeFilter(intent);
3188 }
3189 }
3190
3191 @Override
3192 protected boolean allowFilterResult(
3193 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3194 ServiceInfo filterSi = filter.service.info;
3195 for (int i=dest.size()-1; i>=0; i--) {
3196 ServiceInfo destAi = dest.get(i).serviceInfo;
3197 if (destAi.name == filterSi.name
3198 && destAi.packageName == filterSi.packageName) {
3199 return false;
3200 }
3201 }
3202 return true;
3203 }
3204
3205 @Override
3206 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3207 int match) {
3208 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3209 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3210 return null;
3211 }
3212 final PackageParser.Service service = info.service;
3213 if (mSafeMode && (service.info.applicationInfo.flags
3214 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3215 return null;
3216 }
3217 final ResolveInfo res = new ResolveInfo();
3218 res.serviceInfo = PackageParser.generateServiceInfo(service,
3219 mFlags);
3220 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3221 res.filter = filter;
3222 }
3223 res.priority = info.getPriority();
3224 res.preferredOrder = service.owner.mPreferredOrder;
3225 //System.out.println("Result: " + res.activityInfo.className +
3226 // " = " + res.priority);
3227 res.match = match;
3228 res.isDefault = info.hasDefault;
3229 res.labelRes = info.labelRes;
3230 res.nonLocalizedLabel = info.nonLocalizedLabel;
3231 res.icon = info.icon;
3232 return res;
3233 }
3234
3235 @Override
3236 protected void sortResults(List<ResolveInfo> results) {
3237 Collections.sort(results, mResolvePrioritySorter);
3238 }
3239
3240 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003241 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003243 out.print(prefix); out.print(
3244 Integer.toHexString(System.identityHashCode(filter.service)));
3245 out.print(' ');
3246 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 }
3248
3249// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3250// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3251// final List<ResolveInfo> retList = Lists.newArrayList();
3252// while (i.hasNext()) {
3253// final ResolveInfo resolveInfo = (ResolveInfo) i;
3254// if (isEnabledLP(resolveInfo.serviceInfo)) {
3255// retList.add(resolveInfo);
3256// }
3257// }
3258// return retList;
3259// }
3260
3261 // Keys are String (activity class name), values are Activity.
3262 private final HashMap<ComponentName, PackageParser.Service> mServices
3263 = new HashMap<ComponentName, PackageParser.Service>();
3264 private int mFlags;
3265 };
3266
3267 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3268 new Comparator<ResolveInfo>() {
3269 public int compare(ResolveInfo r1, ResolveInfo r2) {
3270 int v1 = r1.priority;
3271 int v2 = r2.priority;
3272 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3273 if (v1 != v2) {
3274 return (v1 > v2) ? -1 : 1;
3275 }
3276 v1 = r1.preferredOrder;
3277 v2 = r2.preferredOrder;
3278 if (v1 != v2) {
3279 return (v1 > v2) ? -1 : 1;
3280 }
3281 if (r1.isDefault != r2.isDefault) {
3282 return r1.isDefault ? -1 : 1;
3283 }
3284 v1 = r1.match;
3285 v2 = r2.match;
3286 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3287 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3288 }
3289 };
3290
3291 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3292 new Comparator<ProviderInfo>() {
3293 public int compare(ProviderInfo p1, ProviderInfo p2) {
3294 final int v1 = p1.initOrder;
3295 final int v2 = p2.initOrder;
3296 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3297 }
3298 };
3299
3300 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3301 IActivityManager am = ActivityManagerNative.getDefault();
3302 if (am != null) {
3303 try {
3304 final Intent intent = new Intent(action,
3305 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3306 if (extras != null) {
3307 intent.putExtras(extras);
3308 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003309 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 am.broadcastIntent(
3311 null, intent,
3312 null, null, 0, null, null, null, false, false);
3313 } catch (RemoteException ex) {
3314 }
3315 }
3316 }
3317
3318 private final class AppDirObserver extends FileObserver {
3319 public AppDirObserver(String path, int mask, boolean isrom) {
3320 super(path, mask);
3321 mRootDir = path;
3322 mIsRom = isrom;
3323 }
3324
3325 public void onEvent(int event, String path) {
3326 String removedPackage = null;
3327 int removedUid = -1;
3328 String addedPackage = null;
3329 int addedUid = -1;
3330
3331 synchronized (mInstallLock) {
3332 String fullPathStr = null;
3333 File fullPath = null;
3334 if (path != null) {
3335 fullPath = new File(mRootDir, path);
3336 fullPathStr = fullPath.getPath();
3337 }
3338
3339 if (Config.LOGV) Log.v(
3340 TAG, "File " + fullPathStr + " changed: "
3341 + Integer.toHexString(event));
3342
3343 if (!isPackageFilename(path)) {
3344 if (Config.LOGV) Log.v(
3345 TAG, "Ignoring change of non-package file: " + fullPathStr);
3346 return;
3347 }
3348
3349 if ((event&REMOVE_EVENTS) != 0) {
3350 synchronized (mInstallLock) {
3351 PackageParser.Package p = mAppDirs.get(fullPathStr);
3352 if (p != null) {
3353 removePackageLI(p, true);
3354 removedPackage = p.applicationInfo.packageName;
3355 removedUid = p.applicationInfo.uid;
3356 }
3357 }
3358 }
3359
3360 if ((event&ADD_EVENTS) != 0) {
3361 PackageParser.Package p = mAppDirs.get(fullPathStr);
3362 if (p == null) {
3363 p = scanPackageLI(fullPath, fullPath, fullPath,
3364 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3365 PackageParser.PARSE_CHATTY |
3366 PackageParser.PARSE_MUST_BE_APK,
3367 SCAN_MONITOR);
3368 if (p != null) {
3369 synchronized (mPackages) {
3370 grantPermissionsLP(p, false);
3371 }
3372 addedPackage = p.applicationInfo.packageName;
3373 addedUid = p.applicationInfo.uid;
3374 }
3375 }
3376 }
3377
3378 synchronized (mPackages) {
3379 mSettings.writeLP();
3380 }
3381 }
3382
3383 if (removedPackage != null) {
3384 Bundle extras = new Bundle(1);
3385 extras.putInt(Intent.EXTRA_UID, removedUid);
3386 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3387 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3388 }
3389 if (addedPackage != null) {
3390 Bundle extras = new Bundle(1);
3391 extras.putInt(Intent.EXTRA_UID, addedUid);
3392 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3393 }
3394 }
3395
3396 private final String mRootDir;
3397 private final boolean mIsRom;
3398 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 /* Called when a downloaded package installation has been confirmed by the user */
3401 public void installPackage(
3402 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003403 installPackage(packageURI, observer, flags, null);
3404 }
3405
3406 /* Called when a downloaded package installation has been confirmed by the user */
3407 public void installPackage(
3408 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3409 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 mContext.enforceCallingOrSelfPermission(
3411 android.Manifest.permission.INSTALL_PACKAGES, null);
Jacek Surazski65e13172009-04-28 15:26:38 +02003412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 // Queue up an async operation since the package installation may take a little while.
3414 mHandler.post(new Runnable() {
3415 public void run() {
3416 mHandler.removeCallbacks(this);
3417 PackageInstalledInfo res;
3418 synchronized (mInstallLock) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003419 res = installPackageLI(packageURI, flags, true, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 }
3421 if (observer != null) {
3422 try {
3423 observer.packageInstalled(res.name, res.returnCode);
3424 } catch (RemoteException e) {
3425 Log.i(TAG, "Observer no longer exists.");
3426 }
3427 }
3428 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3429 // call appears in the synchronized block above.
3430 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3431 res.removedInfo.sendBroadcast(false, true);
3432 Bundle extras = new Bundle(1);
3433 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003434 final boolean update = res.removedInfo.removedPackage != null;
3435 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3437 }
3438 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3439 res.pkg.applicationInfo.packageName,
3440 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003441 if (update) {
3442 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3443 res.pkg.applicationInfo.packageName,
3444 extras);
3445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 }
3447 Runtime.getRuntime().gc();
3448 }
3449 });
3450 }
3451
3452 class PackageInstalledInfo {
3453 String name;
3454 int uid;
3455 PackageParser.Package pkg;
3456 int returnCode;
3457 PackageRemovedInfo removedInfo;
3458 }
3459
3460 /*
3461 * Install a non-existing package.
3462 */
3463 private void installNewPackageLI(String pkgName,
3464 File tmpPackageFile,
3465 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003466 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003467 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 // Remember this for later, in case we need to rollback this install
3469 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3470 res.name = pkgName;
3471 synchronized(mPackages) {
3472 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3473 // Don't allow installation over an existing package with the same name.
3474 Log.w(TAG, "Attempt to re-install " + pkgName
3475 + " without first uninstalling.");
3476 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3477 return;
3478 }
3479 }
3480 if (destPackageFile.exists()) {
3481 // It's safe to do this because we know (from the above check) that the file
3482 // isn't currently used for an installed package.
3483 destPackageFile.delete();
3484 }
3485 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3486 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3487 destResourceFile, pkg, 0,
3488 SCAN_MONITOR | SCAN_FORCE_DEX
3489 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003490 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3491 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 if (newPackage == null) {
3493 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3494 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3495 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3496 }
3497 } else {
3498 updateSettingsLI(pkgName, tmpPackageFile,
3499 destFilePath, destPackageFile,
3500 destResourceFile, pkg,
3501 newPackage,
3502 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003503 forwardLocked,
3504 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 res);
3506 // delete the partially installed application. the data directory will have to be
3507 // restored if it was already existing
3508 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3509 // remove package from internal structures. Note that we want deletePackageX to
3510 // delete the package data and cache directories that it created in
3511 // scanPackageLocked, unless those directories existed before we even tried to
3512 // install.
3513 deletePackageLI(
3514 pkgName, true,
3515 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3516 res.removedInfo);
3517 }
3518 }
3519 }
3520
3521 private void replacePackageLI(String pkgName,
3522 File tmpPackageFile,
3523 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003524 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003525 String installerPackageName, PackageInstalledInfo res) {
3526
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003527 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 // First find the old package info and check signatures
3529 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003530 oldPackage = mPackages.get(pkgName);
3531 if(checkSignaturesLP(pkg, oldPackage) != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3533 return;
3534 }
3535 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003536 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003538 replaceSystemPackageLI(oldPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003540 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003541 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003543 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003544 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003545 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 }
3547 }
3548
3549 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
3550 File tmpPackageFile,
3551 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003552 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003553 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 PackageParser.Package newPackage = null;
3555 String pkgName = deletedPackage.packageName;
3556 boolean deletedPkg = true;
3557 boolean updatedSettings = false;
Jacek Surazski65e13172009-04-28 15:26:38 +02003558
3559 String oldInstallerPackageName = null;
3560 synchronized (mPackages) {
3561 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3562 }
3563
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003564 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 // First delete the existing package while retaining the data directory
3566 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3567 res.removedInfo)) {
3568 // If the existing package was'nt successfully deleted
3569 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3570 deletedPkg = false;
3571 } else {
3572 // Successfully deleted the old package. Now proceed with re-installation
3573 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3574 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3575 destResourceFile, pkg, parseFlags,
3576 SCAN_MONITOR | SCAN_FORCE_DEX
3577 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003578 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3579 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 if (newPackage == null) {
3581 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3582 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3583 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3584 }
3585 } else {
3586 updateSettingsLI(pkgName, tmpPackageFile,
3587 destFilePath, destPackageFile,
3588 destResourceFile, pkg,
3589 newPackage,
3590 true,
3591 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003592 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 res);
3594 updatedSettings = true;
3595 }
3596 }
3597
3598 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3599 // If we deleted an exisiting package, the old source and resource files that we
3600 // were keeping around in case we needed them (see below) can now be deleted
3601 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3602 final ApplicationInfo installedPackageAppInfo =
3603 newPackage.applicationInfo;
3604 if (!deletedPackageAppInfo.sourceDir
3605 .equals(installedPackageAppInfo.sourceDir)) {
3606 new File(deletedPackageAppInfo.sourceDir).delete();
3607 }
3608 if (!deletedPackageAppInfo.publicSourceDir
3609 .equals(installedPackageAppInfo.publicSourceDir)) {
3610 new File(deletedPackageAppInfo.publicSourceDir).delete();
3611 }
3612 //update signature on the new package setting
3613 //this should always succeed, since we checked the
3614 //signature earlier.
3615 synchronized(mPackages) {
3616 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3617 parseFlags, true);
3618 }
3619 } else {
3620 // remove package from internal structures. Note that we want deletePackageX to
3621 // delete the package data and cache directories that it created in
3622 // scanPackageLocked, unless those directories existed before we even tried to
3623 // install.
3624 if(updatedSettings) {
3625 deletePackageLI(
3626 pkgName, true,
3627 PackageManager.DONT_DELETE_DATA,
3628 res.removedInfo);
3629 }
3630 // Since we failed to install the new package we need to restore the old
3631 // package that we deleted.
3632 if(deletedPkg) {
3633 installPackageLI(
3634 Uri.fromFile(new File(deletedPackage.mPath)),
3635 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003636 ? PackageManager.INSTALL_FORWARD_LOCK
Jacek Surazski65e13172009-04-28 15:26:38 +02003637 : 0, false, oldInstallerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 }
3639 }
3640 }
3641
3642 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
3643 File tmpPackageFile,
3644 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003645 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003646 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 PackageParser.Package newPackage = null;
3648 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003649 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 PackageParser.PARSE_IS_SYSTEM;
3651 String packageName = deletedPackage.packageName;
3652 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3653 if (packageName == null) {
3654 Log.w(TAG, "Attempt to delete null packageName.");
3655 return;
3656 }
3657 PackageParser.Package oldPkg;
3658 PackageSetting oldPkgSetting;
3659 synchronized (mPackages) {
3660 oldPkg = mPackages.get(packageName);
3661 oldPkgSetting = mSettings.mPackages.get(packageName);
3662 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
3663 (oldPkgSetting == null)) {
3664 Log.w(TAG, "Could'nt find package:"+packageName+" information");
3665 return;
3666 }
3667 }
3668 res.removedInfo.uid = oldPkg.applicationInfo.uid;
3669 res.removedInfo.removedPackage = packageName;
3670 // Remove existing system package
3671 removePackageLI(oldPkg, true);
3672 synchronized (mPackages) {
3673 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
3674 }
3675
3676 // Successfully disabled the old package. Now proceed with re-installation
3677 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3678 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3679 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3680 destResourceFile, pkg, parseFlags,
3681 SCAN_MONITOR | SCAN_FORCE_DEX
3682 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003683 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3684 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 if (newPackage == null) {
3686 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3687 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3688 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3689 }
3690 } else {
3691 updateSettingsLI(packageName, tmpPackageFile,
3692 destFilePath, destPackageFile,
3693 destResourceFile, pkg,
3694 newPackage,
3695 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003696 forwardLocked,
3697 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 res);
3699 updatedSettings = true;
3700 }
3701
3702 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3703 //update signature on the new package setting
3704 //this should always succeed, since we checked the
3705 //signature earlier.
3706 synchronized(mPackages) {
3707 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
3708 parseFlags, true);
3709 }
3710 } else {
3711 // Re installation failed. Restore old information
3712 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07003713 if (newPackage != null) {
3714 removePackageLI(newPackage, true);
3715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 // Add back the old system package
3717 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
3718 oldPkgSetting.resourcePath,
3719 oldPkg, parseFlags,
3720 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07003721 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 // Restore the old system information in Settings
3723 synchronized(mPackages) {
3724 if(updatedSettings) {
3725 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02003726 mSettings.setInstallerPackageName(packageName,
3727 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 }
3729 mSettings.writeLP();
3730 }
3731 }
3732 }
3733
3734 private void updateSettingsLI(String pkgName, File tmpPackageFile,
3735 String destFilePath, File destPackageFile,
3736 File destResourceFile,
3737 PackageParser.Package pkg,
3738 PackageParser.Package newPackage,
3739 boolean replacingExistingPackage,
3740 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003741 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 synchronized (mPackages) {
3743 //write settings. the installStatus will be incomplete at this stage.
3744 //note that the new package setting would have already been
3745 //added to mPackages. It hasn't been persisted yet.
3746 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3747 mSettings.writeLP();
3748 }
3749
3750 int retCode = 0;
3751 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3752 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3753 destPackageFile.toString());
3754 if (retCode != 0) {
3755 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3756 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3757 return;
3758 }
3759 }
3760 // XXX There are probably some big issues here: upon doing
3761 // the rename, we have reached the point of no return (the
3762 // original .apk is gone!), so we can't fail. Yet... we can.
3763 if (!tmpPackageFile.renameTo(destPackageFile)) {
3764 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3765 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3766 } else {
3767 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
3768 destResourceFile,
3769 forwardLocked);
3770 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3771 return;
3772 } else {
3773 Log.d(TAG, "New package installed in " + destPackageFile);
3774 }
3775 }
3776 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3777 if (mInstaller != null) {
3778 mInstaller.rmdex(tmpPackageFile.getPath());
3779 }
3780 }
3781
3782 synchronized (mPackages) {
3783 grantPermissionsLP(newPackage, true);
3784 res.name = pkgName;
3785 res.uid = newPackage.applicationInfo.uid;
3786 res.pkg = newPackage;
3787 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02003788 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3790 //to update install status
3791 mSettings.writeLP();
3792 }
3793 }
3794
The Android Open Source Project10592532009-03-18 17:39:46 -07003795 private PackageInstalledInfo installPackageLI(Uri pPackageURI,
Jacek Surazski65e13172009-04-28 15:26:38 +02003796 int pFlags, boolean newInstall, String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 File tmpPackageFile = null;
3798 String pkgName = null;
3799 boolean forwardLocked = false;
3800 boolean replacingExistingPackage = false;
3801 // Result object to be returned
3802 PackageInstalledInfo res = new PackageInstalledInfo();
3803 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3804 res.uid = -1;
3805 res.pkg = null;
3806 res.removedInfo = new PackageRemovedInfo();
3807
3808 main_flow: try {
3809 tmpPackageFile = createTempPackageFile();
3810 if (tmpPackageFile == null) {
3811 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3812 break main_flow;
3813 }
3814 tmpPackageFile.deleteOnExit(); // paranoia
3815 if (pPackageURI.getScheme().equals("file")) {
3816 final File srcPackageFile = new File(pPackageURI.getPath());
3817 // We copy the source package file to a temp file and then rename it to the
3818 // destination file in order to eliminate a window where the package directory
3819 // scanner notices the new package file but it's not completely copied yet.
3820 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3821 Log.e(TAG, "Couldn't copy package file to temp file.");
3822 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3823 break main_flow;
3824 }
3825 } else if (pPackageURI.getScheme().equals("content")) {
3826 ParcelFileDescriptor fd;
3827 try {
3828 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
3829 } catch (FileNotFoundException e) {
3830 Log.e(TAG, "Couldn't open file descriptor from download service.");
3831 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3832 break main_flow;
3833 }
3834 if (fd == null) {
3835 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3836 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3837 break main_flow;
3838 }
3839 if (Config.LOGV) {
3840 Log.v(TAG, "Opened file descriptor from download service.");
3841 }
3842 ParcelFileDescriptor.AutoCloseInputStream
3843 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3844 // We copy the source package file to a temp file and then rename it to the
3845 // destination file in order to eliminate a window where the package directory
3846 // scanner notices the new package file but it's not completely copied yet.
3847 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3848 Log.e(TAG, "Couldn't copy package stream to temp file.");
3849 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3850 break main_flow;
3851 }
3852 } else {
3853 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
3854 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3855 break main_flow;
3856 }
3857 pkgName = PackageParser.parsePackageName(
3858 tmpPackageFile.getAbsolutePath(), 0);
3859 if (pkgName == null) {
3860 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3861 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3862 break main_flow;
3863 }
3864 res.name = pkgName;
3865 //initialize some variables before installing pkg
3866 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003867 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 ? mDrmAppPrivateInstallDir
3869 : mAppInstallDir;
3870 final File destPackageFile = new File(destDir, pkgFileName);
3871 final String destFilePath = destPackageFile.getAbsolutePath();
3872 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003873 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003874 final String publicZipFileName = pkgName + ".zip";
3875 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3876 forwardLocked = true;
3877 } else {
3878 destResourceFile = destPackageFile;
3879 }
3880 // Retrieve PackageSettings and parse package
3881 int parseFlags = PackageParser.PARSE_CHATTY;
3882 parseFlags |= mDefParseFlags;
3883 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3884 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackborn851a5412009-05-08 12:06:44 -07003885 pp.setSdkVersion(mSdkVersion, mSdkCodename);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3887 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3888 if (pkg == null) {
3889 res.returnCode = pp.getParseError();
3890 break main_flow;
3891 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003892 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
3893 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
3894 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
3895 break main_flow;
3896 }
3897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3899 res.returnCode = pp.getParseError();
3900 break main_flow;
3901 }
3902
3903 synchronized (mPackages) {
3904 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003905 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 && mPackages.containsKey(pkgName)) {
3907 replacingExistingPackage = true;
3908 }
3909 }
3910
3911 if(replacingExistingPackage) {
3912 replacePackageLI(pkgName,
3913 tmpPackageFile,
3914 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02003915 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 res);
3917 } else {
3918 installNewPackageLI(pkgName,
3919 tmpPackageFile,
3920 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02003921 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 res);
3923 }
3924 } finally {
3925 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3926 tmpPackageFile.delete();
3927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003929 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 }
3931
3932 private int setPermissionsLI(String pkgName,
3933 PackageParser.Package newPackage,
3934 String destFilePath,
3935 File destResourceFile,
3936 boolean forwardLocked) {
3937 int retCode;
3938 if (forwardLocked) {
3939 try {
3940 extractPublicFiles(newPackage, destResourceFile);
3941 } catch (IOException e) {
3942 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3943 " forward-locked app.");
3944 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3945 } finally {
3946 //TODO clean up the extracted public files
3947 }
3948 if (mInstaller != null) {
3949 retCode = mInstaller.setForwardLockPerm(pkgName,
3950 newPackage.applicationInfo.uid);
3951 } else {
3952 final int filePermissions =
3953 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3954 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3955 newPackage.applicationInfo.uid);
3956 }
3957 } else {
3958 final int filePermissions =
3959 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3960 |FileUtils.S_IROTH;
3961 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3962 }
3963 if (retCode != 0) {
3964 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3965 + ". The return code was: " + retCode);
3966 }
3967 return PackageManager.INSTALL_SUCCEEDED;
3968 }
3969
3970 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3971 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3972 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3973 }
3974
3975 private void extractPublicFiles(PackageParser.Package newPackage,
3976 File publicZipFile) throws IOException {
3977 final ZipOutputStream publicZipOutStream =
3978 new ZipOutputStream(new FileOutputStream(publicZipFile));
3979 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3980
3981 // Copy manifest, resources.arsc and res directory to public zip
3982
3983 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3984 while (privateZipEntries.hasMoreElements()) {
3985 final ZipEntry zipEntry = privateZipEntries.nextElement();
3986 final String zipEntryName = zipEntry.getName();
3987 if ("AndroidManifest.xml".equals(zipEntryName)
3988 || "resources.arsc".equals(zipEntryName)
3989 || zipEntryName.startsWith("res/")) {
3990 try {
3991 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3992 } catch (IOException e) {
3993 try {
3994 publicZipOutStream.close();
3995 throw e;
3996 } finally {
3997 publicZipFile.delete();
3998 }
3999 }
4000 }
4001 }
4002
4003 publicZipOutStream.close();
4004 FileUtils.setPermissions(
4005 publicZipFile.getAbsolutePath(),
4006 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4007 -1, -1);
4008 }
4009
4010 private static void copyZipEntry(ZipEntry zipEntry,
4011 ZipFile inZipFile,
4012 ZipOutputStream outZipStream) throws IOException {
4013 byte[] buffer = new byte[4096];
4014 int num;
4015
4016 ZipEntry newEntry;
4017 if (zipEntry.getMethod() == ZipEntry.STORED) {
4018 // Preserve the STORED method of the input entry.
4019 newEntry = new ZipEntry(zipEntry);
4020 } else {
4021 // Create a new entry so that the compressed len is recomputed.
4022 newEntry = new ZipEntry(zipEntry.getName());
4023 }
4024 outZipStream.putNextEntry(newEntry);
4025
4026 InputStream data = inZipFile.getInputStream(zipEntry);
4027 while ((num = data.read(buffer)) > 0) {
4028 outZipStream.write(buffer, 0, num);
4029 }
4030 outZipStream.flush();
4031 }
4032
4033 private void deleteTempPackageFiles() {
4034 FilenameFilter filter = new FilenameFilter() {
4035 public boolean accept(File dir, String name) {
4036 return name.startsWith("vmdl") && name.endsWith(".tmp");
4037 }
4038 };
4039 String tmpFilesList[] = mAppInstallDir.list(filter);
4040 if(tmpFilesList == null) {
4041 return;
4042 }
4043 for(int i = 0; i < tmpFilesList.length; i++) {
4044 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4045 tmpFile.delete();
4046 }
4047 }
4048
4049 private File createTempPackageFile() {
4050 File tmpPackageFile;
4051 try {
4052 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4053 } catch (IOException e) {
4054 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4055 return null;
4056 }
4057 try {
4058 FileUtils.setPermissions(
4059 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4060 -1, -1);
4061 } catch (IOException e) {
4062 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4063 return null;
4064 }
4065 return tmpPackageFile;
4066 }
4067
4068 public void deletePackage(final String packageName,
4069 final IPackageDeleteObserver observer,
4070 final int flags) {
4071 mContext.enforceCallingOrSelfPermission(
4072 android.Manifest.permission.DELETE_PACKAGES, null);
4073 // Queue up an async operation since the package deletion may take a little while.
4074 mHandler.post(new Runnable() {
4075 public void run() {
4076 mHandler.removeCallbacks(this);
4077 final boolean succeded = deletePackageX(packageName, true, true, flags);
4078 if (observer != null) {
4079 try {
4080 observer.packageDeleted(succeded);
4081 } catch (RemoteException e) {
4082 Log.i(TAG, "Observer no longer exists.");
4083 } //end catch
4084 } //end if
4085 } //end run
4086 });
4087 }
4088
4089 /**
4090 * This method is an internal method that could be get invoked either
4091 * to delete an installed package or to clean up a failed installation.
4092 * After deleting an installed package, a broadcast is sent to notify any
4093 * listeners that the package has been installed. For cleaning up a failed
4094 * installation, the broadcast is not necessary since the package's
4095 * installation wouldn't have sent the initial broadcast either
4096 * The key steps in deleting a package are
4097 * deleting the package information in internal structures like mPackages,
4098 * deleting the packages base directories through installd
4099 * updating mSettings to reflect current status
4100 * persisting settings for later use
4101 * sending a broadcast if necessary
4102 */
4103
4104 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4105 boolean deleteCodeAndResources, int flags) {
4106 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004107 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108
4109 synchronized (mInstallLock) {
4110 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4111 }
4112
4113 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004114 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4115 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4116
4117 // If the removed package was a system update, the old system packaged
4118 // was re-enabled; we need to broadcast this information
4119 if (systemUpdate) {
4120 Bundle extras = new Bundle(1);
4121 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4122 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4123
4124 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4125 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 }
4128 return res;
4129 }
4130
4131 static class PackageRemovedInfo {
4132 String removedPackage;
4133 int uid = -1;
4134 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004135 boolean isRemovedPackageSystemUpdate = false;
4136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004137 void sendBroadcast(boolean fullRemove, boolean replacing) {
4138 Bundle extras = new Bundle(1);
4139 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4140 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4141 if (replacing) {
4142 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4143 }
4144 if (removedPackage != null) {
4145 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4146 }
4147 if (removedUid >= 0) {
4148 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4149 }
4150 }
4151 }
4152
4153 /*
4154 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4155 * flag is not set, the data directory is removed as well.
4156 * make sure this flag is set for partially installed apps. If not its meaningless to
4157 * delete a partially installed application.
4158 */
4159 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
4160 int flags) {
4161 String packageName = p.packageName;
4162 outInfo.removedPackage = packageName;
4163 removePackageLI(p, true);
4164 // Retrieve object to delete permissions for shared user later on
4165 PackageSetting deletedPs;
4166 synchronized (mPackages) {
4167 deletedPs = mSettings.mPackages.get(packageName);
4168 }
4169 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4170 if (mInstaller != null) {
4171 int retCode = mInstaller.remove(packageName);
4172 if (retCode < 0) {
4173 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4174 + packageName + ", retcode=" + retCode);
4175 // we don't consider this to be a failure of the core package deletion
4176 }
4177 } else {
4178 //for emulator
4179 PackageParser.Package pkg = mPackages.get(packageName);
4180 File dataDir = new File(pkg.applicationInfo.dataDir);
4181 dataDir.delete();
4182 }
4183 synchronized (mPackages) {
4184 outInfo.removedUid = mSettings.removePackageLP(packageName);
4185 }
4186 }
4187 synchronized (mPackages) {
4188 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4189 // remove permissions associated with package
4190 mSettings.updateSharedUserPerms (deletedPs);
4191 }
4192 // Save settings now
4193 mSettings.writeLP ();
4194 }
4195 }
4196
4197 /*
4198 * Tries to delete system package.
4199 */
4200 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004201 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 ApplicationInfo applicationInfo = p.applicationInfo;
4203 //applicable for non-partially installed applications only
4204 if (applicationInfo == null) {
4205 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4206 return false;
4207 }
4208 PackageSetting ps = null;
4209 // Confirm if the system package has been updated
4210 // An updated system app can be deleted. This will also have to restore
4211 // the system pkg from system partition
4212 synchronized (mPackages) {
4213 ps = mSettings.getDisabledSystemPkg(p.packageName);
4214 }
4215 if (ps == null) {
4216 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4217 return false;
4218 } else {
4219 Log.i(TAG, "Deleting system pkg from data partition");
4220 }
4221 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004222 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004223 boolean deleteCodeAndResources = false;
4224 if (ps.versionCode < p.mVersionCode) {
4225 // Delete code and resources for downgrades
4226 deleteCodeAndResources = true;
4227 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4228 flags &= ~PackageManager.DONT_DELETE_DATA;
4229 }
4230 } else {
4231 // Preserve data by setting flag
4232 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4233 flags |= PackageManager.DONT_DELETE_DATA;
4234 }
4235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4237 if (!ret) {
4238 return false;
4239 }
4240 synchronized (mPackages) {
4241 // Reinstate the old system package
4242 mSettings.enableSystemPackageLP(p.packageName);
4243 }
4244 // Install the system package
4245 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4246 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4247 SCAN_MONITOR);
4248
4249 if (newPkg == null) {
4250 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4251 return false;
4252 }
4253 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004254 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 mSettings.writeLP();
4256 }
4257 return true;
4258 }
4259
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004260 private void deletePackageResourcesLI(String packageName,
4261 String sourceDir, String publicSourceDir) {
4262 File sourceFile = new File(sourceDir);
4263 if (!sourceFile.exists()) {
4264 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4265 }
4266 // Delete application's code and resources
4267 sourceFile.delete();
4268 final File publicSourceFile = new File(publicSourceDir);
4269 if (publicSourceFile.exists()) {
4270 publicSourceFile.delete();
4271 }
4272 if (mInstaller != null) {
4273 int retCode = mInstaller.rmdex(sourceFile.toString());
4274 if (retCode < 0) {
4275 Log.w(TAG, "Couldn't remove dex file for package: "
4276 + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
4277 // we don't consider this to be a failure of the core package deletion
4278 }
4279 }
4280 }
4281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4283 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4284 ApplicationInfo applicationInfo = p.applicationInfo;
4285 if (applicationInfo == null) {
4286 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4287 return false;
4288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 outInfo.uid = applicationInfo.uid;
4290
4291 // Delete package data from internal structures and also remove data if flag is set
4292 removePackageDataLI(p, outInfo, flags);
4293
4294 // Delete application code and resources
4295 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004296 deletePackageResourcesLI(applicationInfo.packageName,
4297 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 }
4299 return true;
4300 }
4301
4302 /*
4303 * This method handles package deletion in general
4304 */
4305 private boolean deletePackageLI(String packageName,
4306 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4307 if (packageName == null) {
4308 Log.w(TAG, "Attempt to delete null packageName.");
4309 return false;
4310 }
4311 PackageParser.Package p;
4312 boolean dataOnly = false;
4313 synchronized (mPackages) {
4314 p = mPackages.get(packageName);
4315 if (p == null) {
4316 //this retrieves partially installed apps
4317 dataOnly = true;
4318 PackageSetting ps = mSettings.mPackages.get(packageName);
4319 if (ps == null) {
4320 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4321 return false;
4322 }
4323 p = ps.pkg;
4324 }
4325 }
4326 if (p == null) {
4327 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4328 return false;
4329 }
4330
4331 if (dataOnly) {
4332 // Delete application data first
4333 removePackageDataLI(p, outInfo, flags);
4334 return true;
4335 }
4336 // At this point the package should have ApplicationInfo associated with it
4337 if (p.applicationInfo == null) {
4338 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4339 return false;
4340 }
4341 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4342 Log.i(TAG, "Removing system package:"+p.packageName);
4343 // When an updated system application is deleted we delete the existing resources as well and
4344 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004345 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 }
4347 Log.i(TAG, "Removing non-system package:"+p.packageName);
4348 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4349 }
4350
4351 public void clearApplicationUserData(final String packageName,
4352 final IPackageDataObserver observer) {
4353 mContext.enforceCallingOrSelfPermission(
4354 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4355 // Queue up an async operation since the package deletion may take a little while.
4356 mHandler.post(new Runnable() {
4357 public void run() {
4358 mHandler.removeCallbacks(this);
4359 final boolean succeeded;
4360 synchronized (mInstallLock) {
4361 succeeded = clearApplicationUserDataLI(packageName);
4362 }
4363 if (succeeded) {
4364 // invoke DeviceStorageMonitor's update method to clear any notifications
4365 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4366 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4367 if (dsm != null) {
4368 dsm.updateMemory();
4369 }
4370 }
4371 if(observer != null) {
4372 try {
4373 observer.onRemoveCompleted(packageName, succeeded);
4374 } catch (RemoteException e) {
4375 Log.i(TAG, "Observer no longer exists.");
4376 }
4377 } //end if observer
4378 } //end run
4379 });
4380 }
4381
4382 private boolean clearApplicationUserDataLI(String packageName) {
4383 if (packageName == null) {
4384 Log.w(TAG, "Attempt to delete null packageName.");
4385 return false;
4386 }
4387 PackageParser.Package p;
4388 boolean dataOnly = false;
4389 synchronized (mPackages) {
4390 p = mPackages.get(packageName);
4391 if(p == null) {
4392 dataOnly = true;
4393 PackageSetting ps = mSettings.mPackages.get(packageName);
4394 if((ps == null) || (ps.pkg == null)) {
4395 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4396 return false;
4397 }
4398 p = ps.pkg;
4399 }
4400 }
4401 if(!dataOnly) {
4402 //need to check this only for fully installed applications
4403 if (p == null) {
4404 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4405 return false;
4406 }
4407 final ApplicationInfo applicationInfo = p.applicationInfo;
4408 if (applicationInfo == null) {
4409 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4410 return false;
4411 }
4412 }
4413 if (mInstaller != null) {
4414 int retCode = mInstaller.clearUserData(packageName);
4415 if (retCode < 0) {
4416 Log.w(TAG, "Couldn't remove cache files for package: "
4417 + packageName);
4418 return false;
4419 }
4420 }
4421 return true;
4422 }
4423
4424 public void deleteApplicationCacheFiles(final String packageName,
4425 final IPackageDataObserver observer) {
4426 mContext.enforceCallingOrSelfPermission(
4427 android.Manifest.permission.DELETE_CACHE_FILES, null);
4428 // Queue up an async operation since the package deletion may take a little while.
4429 mHandler.post(new Runnable() {
4430 public void run() {
4431 mHandler.removeCallbacks(this);
4432 final boolean succeded;
4433 synchronized (mInstallLock) {
4434 succeded = deleteApplicationCacheFilesLI(packageName);
4435 }
4436 if(observer != null) {
4437 try {
4438 observer.onRemoveCompleted(packageName, succeded);
4439 } catch (RemoteException e) {
4440 Log.i(TAG, "Observer no longer exists.");
4441 }
4442 } //end if observer
4443 } //end run
4444 });
4445 }
4446
4447 private boolean deleteApplicationCacheFilesLI(String packageName) {
4448 if (packageName == null) {
4449 Log.w(TAG, "Attempt to delete null packageName.");
4450 return false;
4451 }
4452 PackageParser.Package p;
4453 synchronized (mPackages) {
4454 p = mPackages.get(packageName);
4455 }
4456 if (p == null) {
4457 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4458 return false;
4459 }
4460 final ApplicationInfo applicationInfo = p.applicationInfo;
4461 if (applicationInfo == null) {
4462 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4463 return false;
4464 }
4465 if (mInstaller != null) {
4466 int retCode = mInstaller.deleteCacheFiles(packageName);
4467 if (retCode < 0) {
4468 Log.w(TAG, "Couldn't remove cache files for package: "
4469 + packageName);
4470 return false;
4471 }
4472 }
4473 return true;
4474 }
4475
4476 public void getPackageSizeInfo(final String packageName,
4477 final IPackageStatsObserver observer) {
4478 mContext.enforceCallingOrSelfPermission(
4479 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4480 // Queue up an async operation since the package deletion may take a little while.
4481 mHandler.post(new Runnable() {
4482 public void run() {
4483 mHandler.removeCallbacks(this);
4484 PackageStats lStats = new PackageStats(packageName);
4485 final boolean succeded;
4486 synchronized (mInstallLock) {
4487 succeded = getPackageSizeInfoLI(packageName, lStats);
4488 }
4489 if(observer != null) {
4490 try {
4491 observer.onGetStatsCompleted(lStats, succeded);
4492 } catch (RemoteException e) {
4493 Log.i(TAG, "Observer no longer exists.");
4494 }
4495 } //end if observer
4496 } //end run
4497 });
4498 }
4499
4500 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4501 if (packageName == null) {
4502 Log.w(TAG, "Attempt to get size of null packageName.");
4503 return false;
4504 }
4505 PackageParser.Package p;
4506 boolean dataOnly = false;
4507 synchronized (mPackages) {
4508 p = mPackages.get(packageName);
4509 if(p == null) {
4510 dataOnly = true;
4511 PackageSetting ps = mSettings.mPackages.get(packageName);
4512 if((ps == null) || (ps.pkg == null)) {
4513 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4514 return false;
4515 }
4516 p = ps.pkg;
4517 }
4518 }
4519 String publicSrcDir = null;
4520 if(!dataOnly) {
4521 final ApplicationInfo applicationInfo = p.applicationInfo;
4522 if (applicationInfo == null) {
4523 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4524 return false;
4525 }
4526 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4527 }
4528 if (mInstaller != null) {
4529 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4530 publicSrcDir, pStats);
4531 if (res < 0) {
4532 return false;
4533 } else {
4534 return true;
4535 }
4536 }
4537 return true;
4538 }
4539
4540
4541 public void addPackageToPreferred(String packageName) {
4542 mContext.enforceCallingOrSelfPermission(
4543 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4544
4545 synchronized (mPackages) {
4546 PackageParser.Package p = mPackages.get(packageName);
4547 if (p == null) {
4548 return;
4549 }
4550 PackageSetting ps = (PackageSetting)p.mExtras;
4551 if (ps != null) {
4552 mSettings.mPreferredPackages.remove(ps);
4553 mSettings.mPreferredPackages.add(0, ps);
4554 updatePreferredIndicesLP();
4555 mSettings.writeLP();
4556 }
4557 }
4558 }
4559
4560 public void removePackageFromPreferred(String packageName) {
4561 mContext.enforceCallingOrSelfPermission(
4562 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4563
4564 synchronized (mPackages) {
4565 PackageParser.Package p = mPackages.get(packageName);
4566 if (p == null) {
4567 return;
4568 }
4569 if (p.mPreferredOrder > 0) {
4570 PackageSetting ps = (PackageSetting)p.mExtras;
4571 if (ps != null) {
4572 mSettings.mPreferredPackages.remove(ps);
4573 p.mPreferredOrder = 0;
4574 updatePreferredIndicesLP();
4575 mSettings.writeLP();
4576 }
4577 }
4578 }
4579 }
4580
4581 private void updatePreferredIndicesLP() {
4582 final ArrayList<PackageSetting> pkgs
4583 = mSettings.mPreferredPackages;
4584 final int N = pkgs.size();
4585 for (int i=0; i<N; i++) {
4586 pkgs.get(i).pkg.mPreferredOrder = N - i;
4587 }
4588 }
4589
4590 public List<PackageInfo> getPreferredPackages(int flags) {
4591 synchronized (mPackages) {
4592 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
4593 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
4594 final int N = pref.size();
4595 for (int i=0; i<N; i++) {
4596 res.add(generatePackageInfo(pref.get(i).pkg, flags));
4597 }
4598 return res;
4599 }
4600 }
4601
4602 public void addPreferredActivity(IntentFilter filter, int match,
4603 ComponentName[] set, ComponentName activity) {
4604 mContext.enforceCallingOrSelfPermission(
4605 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4606
4607 synchronized (mPackages) {
4608 Log.i(TAG, "Adding preferred activity " + activity + ":");
4609 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4610 mSettings.mPreferredActivities.addFilter(
4611 new PreferredActivity(filter, match, set, activity));
4612 mSettings.writeLP();
4613 }
4614 }
4615
Satish Sampath8dbe6122009-06-02 23:35:54 +01004616 public void replacePreferredActivity(IntentFilter filter, int match,
4617 ComponentName[] set, ComponentName activity) {
4618 mContext.enforceCallingOrSelfPermission(
4619 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4620 if (filter.countActions() != 1) {
4621 throw new IllegalArgumentException(
4622 "replacePreferredActivity expects filter to have only 1 action.");
4623 }
4624 if (filter.countCategories() != 1) {
4625 throw new IllegalArgumentException(
4626 "replacePreferredActivity expects filter to have only 1 category.");
4627 }
4628 if (filter.countDataAuthorities() != 0
4629 || filter.countDataPaths() != 0
4630 || filter.countDataSchemes() != 0
4631 || filter.countDataTypes() != 0) {
4632 throw new IllegalArgumentException(
4633 "replacePreferredActivity expects filter to have no data authorities, " +
4634 "paths, schemes or types.");
4635 }
4636 synchronized (mPackages) {
4637 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4638 String action = filter.getAction(0);
4639 String category = filter.getCategory(0);
4640 while (it.hasNext()) {
4641 PreferredActivity pa = it.next();
4642 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
4643 it.remove();
4644 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
4645 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4646 }
4647 }
4648 addPreferredActivity(filter, match, set, activity);
4649 }
4650 }
4651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 public void clearPackagePreferredActivities(String packageName) {
4653 mContext.enforceCallingOrSelfPermission(
4654 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4655
4656 synchronized (mPackages) {
4657 if (clearPackagePreferredActivitiesLP(packageName)) {
4658 mSettings.writeLP();
4659 }
4660 }
4661 }
4662
4663 boolean clearPackagePreferredActivitiesLP(String packageName) {
4664 boolean changed = false;
4665 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4666 while (it.hasNext()) {
4667 PreferredActivity pa = it.next();
4668 if (pa.mActivity.getPackageName().equals(packageName)) {
4669 it.remove();
4670 changed = true;
4671 }
4672 }
4673 return changed;
4674 }
4675
4676 public int getPreferredActivities(List<IntentFilter> outFilters,
4677 List<ComponentName> outActivities, String packageName) {
4678
4679 int num = 0;
4680 synchronized (mPackages) {
4681 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4682 while (it.hasNext()) {
4683 PreferredActivity pa = it.next();
4684 if (packageName == null
4685 || pa.mActivity.getPackageName().equals(packageName)) {
4686 if (outFilters != null) {
4687 outFilters.add(new IntentFilter(pa));
4688 }
4689 if (outActivities != null) {
4690 outActivities.add(pa.mActivity);
4691 }
4692 }
4693 }
4694 }
4695
4696 return num;
4697 }
4698
4699 public void setApplicationEnabledSetting(String appPackageName,
4700 int newState, int flags) {
4701 setEnabledSetting(appPackageName, null, newState, flags);
4702 }
4703
4704 public void setComponentEnabledSetting(ComponentName componentName,
4705 int newState, int flags) {
4706 setEnabledSetting(componentName.getPackageName(),
4707 componentName.getClassName(), newState, flags);
4708 }
4709
4710 private void setEnabledSetting(
4711 final String packageNameStr, String classNameStr, int newState, final int flags) {
4712 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
4713 || newState == COMPONENT_ENABLED_STATE_ENABLED
4714 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
4715 throw new IllegalArgumentException("Invalid new component state: "
4716 + newState);
4717 }
4718 PackageSetting pkgSetting;
4719 final int uid = Binder.getCallingUid();
4720 final int permission = mContext.checkCallingPermission(
4721 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
4722 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4723 int packageUid = -1;
4724 synchronized (mPackages) {
4725 pkgSetting = mSettings.mPackages.get(packageNameStr);
4726 if (pkgSetting == null) {
4727 if (classNameStr == null) {
4728 throw new IllegalArgumentException(
4729 "Unknown package: " + packageNameStr);
4730 }
4731 throw new IllegalArgumentException(
4732 "Unknown component: " + packageNameStr
4733 + "/" + classNameStr);
4734 }
4735 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4736 throw new SecurityException(
4737 "Permission Denial: attempt to change component state from pid="
4738 + Binder.getCallingPid()
4739 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
4740 }
4741 packageUid = pkgSetting.userId;
4742 if (classNameStr == null) {
4743 // We're dealing with an application/package level state change
4744 pkgSetting.enabled = newState;
4745 } else {
4746 // We're dealing with a component level state change
4747 switch (newState) {
4748 case COMPONENT_ENABLED_STATE_ENABLED:
4749 pkgSetting.enableComponentLP(classNameStr);
4750 break;
4751 case COMPONENT_ENABLED_STATE_DISABLED:
4752 pkgSetting.disableComponentLP(classNameStr);
4753 break;
4754 case COMPONENT_ENABLED_STATE_DEFAULT:
4755 pkgSetting.restoreComponentLP(classNameStr);
4756 break;
4757 default:
4758 Log.e(TAG, "Invalid new component state: " + newState);
4759 }
4760 }
4761 mSettings.writeLP();
4762 }
4763
4764 long callingId = Binder.clearCallingIdentity();
4765 try {
4766 Bundle extras = new Bundle(2);
4767 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
4768 (flags&PackageManager.DONT_KILL_APP) != 0);
4769 extras.putInt(Intent.EXTRA_UID, packageUid);
4770 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
4771 } finally {
4772 Binder.restoreCallingIdentity(callingId);
4773 }
4774 }
4775
Jacek Surazski65e13172009-04-28 15:26:38 +02004776 public String getInstallerPackageName(String packageName) {
4777 synchronized (mPackages) {
4778 PackageSetting pkg = mSettings.mPackages.get(packageName);
4779 if (pkg == null) {
4780 throw new IllegalArgumentException("Unknown package: " + packageName);
4781 }
4782 return pkg.installerPackageName;
4783 }
4784 }
4785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 public int getApplicationEnabledSetting(String appPackageName) {
4787 synchronized (mPackages) {
4788 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
4789 if (pkg == null) {
4790 throw new IllegalArgumentException("Unknown package: " + appPackageName);
4791 }
4792 return pkg.enabled;
4793 }
4794 }
4795
4796 public int getComponentEnabledSetting(ComponentName componentName) {
4797 synchronized (mPackages) {
4798 final String packageNameStr = componentName.getPackageName();
4799 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
4800 if (pkg == null) {
4801 throw new IllegalArgumentException("Unknown component: " + componentName);
4802 }
4803 final String classNameStr = componentName.getClassName();
4804 return pkg.currentEnabledStateLP(classNameStr);
4805 }
4806 }
4807
4808 public void enterSafeMode() {
4809 if (!mSystemReady) {
4810 mSafeMode = true;
4811 }
4812 }
4813
4814 public void systemReady() {
4815 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07004816
4817 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07004818 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07004819 mContext.getContentResolver(),
4820 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07004821 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07004822 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07004823 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07004824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004825 }
4826
4827 public boolean isSafeMode() {
4828 return mSafeMode;
4829 }
4830
4831 public boolean hasSystemUidErrors() {
4832 return mHasSystemUidErrors;
4833 }
4834
4835 static String arrayToString(int[] array) {
4836 StringBuffer buf = new StringBuffer(128);
4837 buf.append('[');
4838 if (array != null) {
4839 for (int i=0; i<array.length; i++) {
4840 if (i > 0) buf.append(", ");
4841 buf.append(array[i]);
4842 }
4843 }
4844 buf.append(']');
4845 return buf.toString();
4846 }
4847
4848 @Override
4849 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4850 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4851 != PackageManager.PERMISSION_GRANTED) {
4852 pw.println("Permission Denial: can't dump ActivityManager from from pid="
4853 + Binder.getCallingPid()
4854 + ", uid=" + Binder.getCallingUid()
4855 + " without permission "
4856 + android.Manifest.permission.DUMP);
4857 return;
4858 }
4859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 synchronized (mPackages) {
4861 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004862 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 pw.println(" ");
4864 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004865 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 pw.println(" ");
4867 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004868 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 pw.println(" ");
4870 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004871 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 pw.println(" ");
4873 pw.println("Preferred Packages:");
4874 {
4875 for (PackageSetting ps : mSettings.mPreferredPackages) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004876 pw.print(" "); pw.println(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 }
4878 }
4879 pw.println(" ");
4880 pw.println("Permissions:");
4881 {
4882 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004883 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
4884 pw.print(Integer.toHexString(System.identityHashCode(p)));
4885 pw.println("):");
4886 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
4887 pw.print(" uid="); pw.print(p.uid);
4888 pw.print(" gids="); pw.print(arrayToString(p.gids));
4889 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 }
4891 }
4892 pw.println(" ");
4893 pw.println("Packages:");
4894 {
4895 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004896 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
4897 pw.print(Integer.toHexString(System.identityHashCode(ps)));
4898 pw.println("):");
4899 pw.print(" userId="); pw.print(ps.userId);
4900 pw.print(" gids="); pw.println(arrayToString(ps.gids));
4901 pw.print(" sharedUser="); pw.println(ps.sharedUser);
4902 pw.print(" pkg="); pw.println(ps.pkg);
4903 pw.print(" codePath="); pw.println(ps.codePathString);
4904 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004906 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07004907 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004908 pw.print(" supportsScreens=[");
4909 boolean first = true;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07004910 if ((ps.pkg.applicationInfo.flags &
4911 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004912 if (!first) pw.print(", ");
4913 first = false;
4914 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07004915 }
4916 if ((ps.pkg.applicationInfo.flags &
4917 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004918 if (!first) pw.print(", ");
4919 first = false;
4920 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07004921 }
4922 if ((ps.pkg.applicationInfo.flags &
4923 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004924 if (!first) pw.print(", ");
4925 first = false;
4926 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07004927 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004928 if ((ps.pkg.applicationInfo.flags &
4929 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004930 if (!first) pw.print(", ");
4931 first = false;
4932 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004933 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004934 if ((ps.pkg.applicationInfo.flags &
4935 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
4936 if (!first) pw.print(", ");
4937 first = false;
4938 pw.print("anyDensity");
4939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07004941 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004942 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
4943 pw.print(" signatures="); pw.println(ps.signatures);
4944 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
4945 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
4946 pw.print(" installStatus="); pw.print(ps.installStatus);
4947 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 if (ps.disabledComponents.size() > 0) {
4949 pw.println(" disabledComponents:");
4950 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004951 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 }
4953 }
4954 if (ps.enabledComponents.size() > 0) {
4955 pw.println(" enabledComponents:");
4956 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004957 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 }
4959 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004960 if (ps.grantedPermissions.size() > 0) {
4961 pw.println(" grantedPermissions:");
4962 for (String s : ps.grantedPermissions) {
4963 pw.print(" "); pw.println(s);
4964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004966 if (ps.loadedPermissions.size() > 0) {
4967 pw.println(" loadedPermissions:");
4968 for (String s : ps.loadedPermissions) {
4969 pw.print(" "); pw.println(s);
4970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 }
4972 }
4973 }
4974 pw.println(" ");
4975 pw.println("Shared Users:");
4976 {
4977 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004978 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
4979 pw.print(Integer.toHexString(System.identityHashCode(su)));
4980 pw.println("):");
4981 pw.print(" userId="); pw.print(su.userId);
4982 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 pw.println(" grantedPermissions:");
4984 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004985 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 }
4987 pw.println(" loadedPermissions:");
4988 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004989 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 }
4991 }
4992 }
4993 pw.println(" ");
4994 pw.println("Settings parse messages:");
4995 pw.println(mSettings.mReadMessages.toString());
4996 }
4997 }
4998
4999 static final class BasePermission {
5000 final static int TYPE_NORMAL = 0;
5001 final static int TYPE_BUILTIN = 1;
5002 final static int TYPE_DYNAMIC = 2;
5003
5004 final String name;
5005 final String sourcePackage;
5006 final int type;
5007 PackageParser.Permission perm;
5008 PermissionInfo pendingInfo;
5009 int uid;
5010 int[] gids;
5011
5012 BasePermission(String _name, String _sourcePackage, int _type) {
5013 name = _name;
5014 sourcePackage = _sourcePackage;
5015 type = _type;
5016 }
5017 }
5018
5019 static class PackageSignatures {
5020 private Signature[] mSignatures;
5021
5022 PackageSignatures(Signature[] sigs) {
5023 assignSignatures(sigs);
5024 }
5025
5026 PackageSignatures() {
5027 }
5028
5029 void writeXml(XmlSerializer serializer, String tagName,
5030 ArrayList<Signature> pastSignatures) throws IOException {
5031 if (mSignatures == null) {
5032 return;
5033 }
5034 serializer.startTag(null, tagName);
5035 serializer.attribute(null, "count",
5036 Integer.toString(mSignatures.length));
5037 for (int i=0; i<mSignatures.length; i++) {
5038 serializer.startTag(null, "cert");
5039 final Signature sig = mSignatures[i];
5040 final int sigHash = sig.hashCode();
5041 final int numPast = pastSignatures.size();
5042 int j;
5043 for (j=0; j<numPast; j++) {
5044 Signature pastSig = pastSignatures.get(j);
5045 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5046 serializer.attribute(null, "index", Integer.toString(j));
5047 break;
5048 }
5049 }
5050 if (j >= numPast) {
5051 pastSignatures.add(sig);
5052 serializer.attribute(null, "index", Integer.toString(numPast));
5053 serializer.attribute(null, "key", sig.toCharsString());
5054 }
5055 serializer.endTag(null, "cert");
5056 }
5057 serializer.endTag(null, tagName);
5058 }
5059
5060 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5061 throws IOException, XmlPullParserException {
5062 String countStr = parser.getAttributeValue(null, "count");
5063 if (countStr == null) {
5064 reportSettingsProblem(Log.WARN,
5065 "Error in package manager settings: <signatures> has"
5066 + " no count at " + parser.getPositionDescription());
5067 XmlUtils.skipCurrentTag(parser);
5068 }
5069 final int count = Integer.parseInt(countStr);
5070 mSignatures = new Signature[count];
5071 int pos = 0;
5072
5073 int outerDepth = parser.getDepth();
5074 int type;
5075 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5076 && (type != XmlPullParser.END_TAG
5077 || parser.getDepth() > outerDepth)) {
5078 if (type == XmlPullParser.END_TAG
5079 || type == XmlPullParser.TEXT) {
5080 continue;
5081 }
5082
5083 String tagName = parser.getName();
5084 if (tagName.equals("cert")) {
5085 if (pos < count) {
5086 String index = parser.getAttributeValue(null, "index");
5087 if (index != null) {
5088 try {
5089 int idx = Integer.parseInt(index);
5090 String key = parser.getAttributeValue(null, "key");
5091 if (key == null) {
5092 if (idx >= 0 && idx < pastSignatures.size()) {
5093 Signature sig = pastSignatures.get(idx);
5094 if (sig != null) {
5095 mSignatures[pos] = pastSignatures.get(idx);
5096 pos++;
5097 } else {
5098 reportSettingsProblem(Log.WARN,
5099 "Error in package manager settings: <cert> "
5100 + "index " + index + " is not defined at "
5101 + parser.getPositionDescription());
5102 }
5103 } else {
5104 reportSettingsProblem(Log.WARN,
5105 "Error in package manager settings: <cert> "
5106 + "index " + index + " is out of bounds at "
5107 + parser.getPositionDescription());
5108 }
5109 } else {
5110 while (pastSignatures.size() <= idx) {
5111 pastSignatures.add(null);
5112 }
5113 Signature sig = new Signature(key);
5114 pastSignatures.set(idx, sig);
5115 mSignatures[pos] = sig;
5116 pos++;
5117 }
5118 } catch (NumberFormatException e) {
5119 reportSettingsProblem(Log.WARN,
5120 "Error in package manager settings: <cert> "
5121 + "index " + index + " is not a number at "
5122 + parser.getPositionDescription());
5123 }
5124 } else {
5125 reportSettingsProblem(Log.WARN,
5126 "Error in package manager settings: <cert> has"
5127 + " no index at " + parser.getPositionDescription());
5128 }
5129 } else {
5130 reportSettingsProblem(Log.WARN,
5131 "Error in package manager settings: too "
5132 + "many <cert> tags, expected " + count
5133 + " at " + parser.getPositionDescription());
5134 }
5135 } else {
5136 reportSettingsProblem(Log.WARN,
5137 "Unknown element under <cert>: "
5138 + parser.getName());
5139 }
5140 XmlUtils.skipCurrentTag(parser);
5141 }
5142
5143 if (pos < count) {
5144 // Should never happen -- there is an error in the written
5145 // settings -- but if it does we don't want to generate
5146 // a bad array.
5147 Signature[] newSigs = new Signature[pos];
5148 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5149 mSignatures = newSigs;
5150 }
5151 }
5152
5153 /**
5154 * If any of the given 'sigs' is contained in the existing signatures,
5155 * then completely replace the current signatures with the ones in
5156 * 'sigs'. This is used for updating an existing package to a newly
5157 * installed version.
5158 */
5159 boolean updateSignatures(Signature[] sigs, boolean update) {
5160 if (mSignatures == null) {
5161 if (update) {
5162 assignSignatures(sigs);
5163 }
5164 return true;
5165 }
5166 if (sigs == null) {
5167 return false;
5168 }
5169
5170 for (int i=0; i<sigs.length; i++) {
5171 Signature sig = sigs[i];
5172 for (int j=0; j<mSignatures.length; j++) {
5173 if (mSignatures[j].equals(sig)) {
5174 if (update) {
5175 assignSignatures(sigs);
5176 }
5177 return true;
5178 }
5179 }
5180 }
5181 return false;
5182 }
5183
5184 /**
5185 * If any of the given 'sigs' is contained in the existing signatures,
5186 * then add in any new signatures found in 'sigs'. This is used for
5187 * including a new package into an existing shared user id.
5188 */
5189 boolean mergeSignatures(Signature[] sigs, boolean update) {
5190 if (mSignatures == null) {
5191 if (update) {
5192 assignSignatures(sigs);
5193 }
5194 return true;
5195 }
5196 if (sigs == null) {
5197 return false;
5198 }
5199
5200 Signature[] added = null;
5201 int addedCount = 0;
5202 boolean haveMatch = false;
5203 for (int i=0; i<sigs.length; i++) {
5204 Signature sig = sigs[i];
5205 boolean found = false;
5206 for (int j=0; j<mSignatures.length; j++) {
5207 if (mSignatures[j].equals(sig)) {
5208 found = true;
5209 haveMatch = true;
5210 break;
5211 }
5212 }
5213
5214 if (!found) {
5215 if (added == null) {
5216 added = new Signature[sigs.length];
5217 }
5218 added[i] = sig;
5219 addedCount++;
5220 }
5221 }
5222
5223 if (!haveMatch) {
5224 // Nothing matched -- reject the new signatures.
5225 return false;
5226 }
5227 if (added == null) {
5228 // Completely matched -- nothing else to do.
5229 return true;
5230 }
5231
5232 // Add additional signatures in.
5233 if (update) {
5234 Signature[] total = new Signature[addedCount+mSignatures.length];
5235 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5236 int j = mSignatures.length;
5237 for (int i=0; i<added.length; i++) {
5238 if (added[i] != null) {
5239 total[j] = added[i];
5240 j++;
5241 }
5242 }
5243 mSignatures = total;
5244 }
5245 return true;
5246 }
5247
5248 private void assignSignatures(Signature[] sigs) {
5249 if (sigs == null) {
5250 mSignatures = null;
5251 return;
5252 }
5253 mSignatures = new Signature[sigs.length];
5254 for (int i=0; i<sigs.length; i++) {
5255 mSignatures[i] = sigs[i];
5256 }
5257 }
5258
5259 @Override
5260 public String toString() {
5261 StringBuffer buf = new StringBuffer(128);
5262 buf.append("PackageSignatures{");
5263 buf.append(Integer.toHexString(System.identityHashCode(this)));
5264 buf.append(" [");
5265 if (mSignatures != null) {
5266 for (int i=0; i<mSignatures.length; i++) {
5267 if (i > 0) buf.append(", ");
5268 buf.append(Integer.toHexString(
5269 System.identityHashCode(mSignatures[i])));
5270 }
5271 }
5272 buf.append("]}");
5273 return buf.toString();
5274 }
5275 }
5276
5277 static class PreferredActivity extends IntentFilter {
5278 final int mMatch;
5279 final String[] mSetPackages;
5280 final String[] mSetClasses;
5281 final String[] mSetComponents;
5282 final ComponentName mActivity;
5283 final String mShortActivity;
5284 String mParseError;
5285
5286 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5287 ComponentName activity) {
5288 super(filter);
5289 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5290 mActivity = activity;
5291 mShortActivity = activity.flattenToShortString();
5292 mParseError = null;
5293 if (set != null) {
5294 final int N = set.length;
5295 String[] myPackages = new String[N];
5296 String[] myClasses = new String[N];
5297 String[] myComponents = new String[N];
5298 for (int i=0; i<N; i++) {
5299 ComponentName cn = set[i];
5300 if (cn == null) {
5301 mSetPackages = null;
5302 mSetClasses = null;
5303 mSetComponents = null;
5304 return;
5305 }
5306 myPackages[i] = cn.getPackageName().intern();
5307 myClasses[i] = cn.getClassName().intern();
5308 myComponents[i] = cn.flattenToShortString().intern();
5309 }
5310 mSetPackages = myPackages;
5311 mSetClasses = myClasses;
5312 mSetComponents = myComponents;
5313 } else {
5314 mSetPackages = null;
5315 mSetClasses = null;
5316 mSetComponents = null;
5317 }
5318 }
5319
5320 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5321 IOException {
5322 mShortActivity = parser.getAttributeValue(null, "name");
5323 mActivity = ComponentName.unflattenFromString(mShortActivity);
5324 if (mActivity == null) {
5325 mParseError = "Bad activity name " + mShortActivity;
5326 }
5327 String matchStr = parser.getAttributeValue(null, "match");
5328 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5329 String setCountStr = parser.getAttributeValue(null, "set");
5330 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5331
5332 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5333 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5334 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5335
5336 int setPos = 0;
5337
5338 int outerDepth = parser.getDepth();
5339 int type;
5340 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5341 && (type != XmlPullParser.END_TAG
5342 || parser.getDepth() > outerDepth)) {
5343 if (type == XmlPullParser.END_TAG
5344 || type == XmlPullParser.TEXT) {
5345 continue;
5346 }
5347
5348 String tagName = parser.getName();
5349 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5350 // + parser.getDepth() + " tag=" + tagName);
5351 if (tagName.equals("set")) {
5352 String name = parser.getAttributeValue(null, "name");
5353 if (name == null) {
5354 if (mParseError == null) {
5355 mParseError = "No name in set tag in preferred activity "
5356 + mShortActivity;
5357 }
5358 } else if (setPos >= setCount) {
5359 if (mParseError == null) {
5360 mParseError = "Too many set tags in preferred activity "
5361 + mShortActivity;
5362 }
5363 } else {
5364 ComponentName cn = ComponentName.unflattenFromString(name);
5365 if (cn == null) {
5366 if (mParseError == null) {
5367 mParseError = "Bad set name " + name + " in preferred activity "
5368 + mShortActivity;
5369 }
5370 } else {
5371 myPackages[setPos] = cn.getPackageName();
5372 myClasses[setPos] = cn.getClassName();
5373 myComponents[setPos] = name;
5374 setPos++;
5375 }
5376 }
5377 XmlUtils.skipCurrentTag(parser);
5378 } else if (tagName.equals("filter")) {
5379 //Log.i(TAG, "Starting to parse filter...");
5380 readFromXml(parser);
5381 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5382 // + parser.getDepth() + " tag=" + parser.getName());
5383 } else {
5384 reportSettingsProblem(Log.WARN,
5385 "Unknown element under <preferred-activities>: "
5386 + parser.getName());
5387 XmlUtils.skipCurrentTag(parser);
5388 }
5389 }
5390
5391 if (setPos != setCount) {
5392 if (mParseError == null) {
5393 mParseError = "Not enough set tags (expected " + setCount
5394 + " but found " + setPos + ") in " + mShortActivity;
5395 }
5396 }
5397
5398 mSetPackages = myPackages;
5399 mSetClasses = myClasses;
5400 mSetComponents = myComponents;
5401 }
5402
5403 public void writeToXml(XmlSerializer serializer) throws IOException {
5404 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5405 serializer.attribute(null, "name", mShortActivity);
5406 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5407 serializer.attribute(null, "set", Integer.toString(NS));
5408 for (int s=0; s<NS; s++) {
5409 serializer.startTag(null, "set");
5410 serializer.attribute(null, "name", mSetComponents[s]);
5411 serializer.endTag(null, "set");
5412 }
5413 serializer.startTag(null, "filter");
5414 super.writeToXml(serializer);
5415 serializer.endTag(null, "filter");
5416 }
5417
5418 boolean sameSet(List<ResolveInfo> query, int priority) {
5419 if (mSetPackages == null) return false;
5420 final int NQ = query.size();
5421 final int NS = mSetPackages.length;
5422 int numMatch = 0;
5423 for (int i=0; i<NQ; i++) {
5424 ResolveInfo ri = query.get(i);
5425 if (ri.priority != priority) continue;
5426 ActivityInfo ai = ri.activityInfo;
5427 boolean good = false;
5428 for (int j=0; j<NS; j++) {
5429 if (mSetPackages[j].equals(ai.packageName)
5430 && mSetClasses[j].equals(ai.name)) {
5431 numMatch++;
5432 good = true;
5433 break;
5434 }
5435 }
5436 if (!good) return false;
5437 }
5438 return numMatch == NS;
5439 }
5440 }
5441
5442 static class GrantedPermissions {
5443 final int pkgFlags;
5444
5445 HashSet<String> grantedPermissions = new HashSet<String>();
5446 int[] gids;
5447
5448 HashSet<String> loadedPermissions = new HashSet<String>();
5449
5450 GrantedPermissions(int pkgFlags) {
5451 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5452 }
5453 }
5454
5455 /**
5456 * Settings base class for pending and resolved classes.
5457 */
5458 static class PackageSettingBase extends GrantedPermissions {
5459 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005460 File codePath;
5461 String codePathString;
5462 File resourcePath;
5463 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 private long timeStamp;
5465 private String timeStampString = "0";
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005466 final int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467
5468 PackageSignatures signatures = new PackageSignatures();
5469
5470 boolean permissionsFixed;
5471
5472 /* Explicitly disabled components */
5473 HashSet<String> disabledComponents = new HashSet<String>(0);
5474 /* Explicitly enabled components */
5475 HashSet<String> enabledComponents = new HashSet<String>(0);
5476 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5477 int installStatus = PKG_INSTALL_COMPLETE;
Jacek Surazski65e13172009-04-28 15:26:38 +02005478
5479 /* package name of the app that installed this package */
5480 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481
5482 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005483 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484 super(pkgFlags);
5485 this.name = name;
5486 this.codePath = codePath;
5487 this.codePathString = codePath.toString();
5488 this.resourcePath = resourcePath;
5489 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005490 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 }
5492
Jacek Surazski65e13172009-04-28 15:26:38 +02005493 public void setInstallerPackageName(String packageName) {
5494 installerPackageName = packageName;
5495 }
5496
5497 String getInstallerPackageName() {
5498 return installerPackageName;
5499 }
5500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 public void setInstallStatus(int newStatus) {
5502 installStatus = newStatus;
5503 }
5504
5505 public int getInstallStatus() {
5506 return installStatus;
5507 }
5508
5509 public void setTimeStamp(long newStamp) {
5510 if (newStamp != timeStamp) {
5511 timeStamp = newStamp;
5512 timeStampString = Long.toString(newStamp);
5513 }
5514 }
5515
5516 public void setTimeStamp(long newStamp, String newStampStr) {
5517 timeStamp = newStamp;
5518 timeStampString = newStampStr;
5519 }
5520
5521 public long getTimeStamp() {
5522 return timeStamp;
5523 }
5524
5525 public String getTimeStampStr() {
5526 return timeStampString;
5527 }
5528
5529 public void copyFrom(PackageSettingBase base) {
5530 grantedPermissions = base.grantedPermissions;
5531 gids = base.gids;
5532 loadedPermissions = base.loadedPermissions;
5533
5534 timeStamp = base.timeStamp;
5535 timeStampString = base.timeStampString;
5536 signatures = base.signatures;
5537 permissionsFixed = base.permissionsFixed;
5538 disabledComponents = base.disabledComponents;
5539 enabledComponents = base.enabledComponents;
5540 enabled = base.enabled;
5541 installStatus = base.installStatus;
5542 }
5543
5544 void enableComponentLP(String componentClassName) {
5545 disabledComponents.remove(componentClassName);
5546 enabledComponents.add(componentClassName);
5547 }
5548
5549 void disableComponentLP(String componentClassName) {
5550 enabledComponents.remove(componentClassName);
5551 disabledComponents.add(componentClassName);
5552 }
5553
5554 void restoreComponentLP(String componentClassName) {
5555 enabledComponents.remove(componentClassName);
5556 disabledComponents.remove(componentClassName);
5557 }
5558
5559 int currentEnabledStateLP(String componentName) {
5560 if (enabledComponents.contains(componentName)) {
5561 return COMPONENT_ENABLED_STATE_ENABLED;
5562 } else if (disabledComponents.contains(componentName)) {
5563 return COMPONENT_ENABLED_STATE_DISABLED;
5564 } else {
5565 return COMPONENT_ENABLED_STATE_DEFAULT;
5566 }
5567 }
5568 }
5569
5570 /**
5571 * Settings data for a particular package we know about.
5572 */
5573 static final class PackageSetting extends PackageSettingBase {
5574 int userId;
5575 PackageParser.Package pkg;
5576 SharedUserSetting sharedUser;
5577
5578 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005579 int pVersionCode, int pkgFlags) {
5580 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 }
5582
5583 @Override
5584 public String toString() {
5585 return "PackageSetting{"
5586 + Integer.toHexString(System.identityHashCode(this))
5587 + " " + name + "/" + userId + "}";
5588 }
5589 }
5590
5591 /**
5592 * Settings data for a particular shared user ID we know about.
5593 */
5594 static final class SharedUserSetting extends GrantedPermissions {
5595 final String name;
5596 int userId;
5597 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5598 final PackageSignatures signatures = new PackageSignatures();
5599
5600 SharedUserSetting(String _name, int _pkgFlags) {
5601 super(_pkgFlags);
5602 name = _name;
5603 }
5604
5605 @Override
5606 public String toString() {
5607 return "SharedUserSetting{"
5608 + Integer.toHexString(System.identityHashCode(this))
5609 + " " + name + "/" + userId + "}";
5610 }
5611 }
5612
5613 /**
5614 * Holds information about dynamic settings.
5615 */
5616 private static final class Settings {
5617 private final File mSettingsFilename;
5618 private final File mBackupSettingsFilename;
5619 private final HashMap<String, PackageSetting> mPackages =
5620 new HashMap<String, PackageSetting>();
5621 // The user's preferred packages/applications, in order of preference.
5622 // First is the most preferred.
5623 private final ArrayList<PackageSetting> mPreferredPackages =
5624 new ArrayList<PackageSetting>();
5625 // List of replaced system applications
5626 final HashMap<String, PackageSetting> mDisabledSysPackages =
5627 new HashMap<String, PackageSetting>();
5628
5629 // The user's preferred activities associated with particular intent
5630 // filters.
5631 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
5632 new IntentResolver<PreferredActivity, PreferredActivity>() {
5633 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005634 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005636 out.print(prefix); out.print(
5637 Integer.toHexString(System.identityHashCode(filter)));
5638 out.print(' ');
5639 out.print(filter.mActivity.flattenToShortString());
5640 out.print(" match=0x");
5641 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005643 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005645 out.print(prefix); out.print(" ");
5646 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 }
5648 }
5649 }
5650 };
5651 private final HashMap<String, SharedUserSetting> mSharedUsers =
5652 new HashMap<String, SharedUserSetting>();
5653 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
5654 private final SparseArray<Object> mOtherUserIds =
5655 new SparseArray<Object>();
5656
5657 // For reading/writing settings file.
5658 private final ArrayList<Signature> mPastSignatures =
5659 new ArrayList<Signature>();
5660
5661 // Mapping from permission names to info about them.
5662 final HashMap<String, BasePermission> mPermissions =
5663 new HashMap<String, BasePermission>();
5664
5665 // Mapping from permission tree names to info about them.
5666 final HashMap<String, BasePermission> mPermissionTrees =
5667 new HashMap<String, BasePermission>();
5668
5669 private final ArrayList<String> mPendingPreferredPackages
5670 = new ArrayList<String>();
5671
5672 private final StringBuilder mReadMessages = new StringBuilder();
5673
5674 private static final class PendingPackage extends PackageSettingBase {
5675 final int sharedId;
5676
5677 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005678 int sharedId, int pVersionCode, int pkgFlags) {
5679 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 this.sharedId = sharedId;
5681 }
5682 }
5683 private final ArrayList<PendingPackage> mPendingPackages
5684 = new ArrayList<PendingPackage>();
5685
5686 Settings() {
5687 File dataDir = Environment.getDataDirectory();
5688 File systemDir = new File(dataDir, "system");
5689 systemDir.mkdirs();
5690 FileUtils.setPermissions(systemDir.toString(),
5691 FileUtils.S_IRWXU|FileUtils.S_IRWXG
5692 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
5693 -1, -1);
5694 mSettingsFilename = new File(systemDir, "packages.xml");
5695 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
5696 }
5697
5698 PackageSetting getPackageLP(PackageParser.Package pkg,
5699 SharedUserSetting sharedUser, File codePath, File resourcePath,
5700 int pkgFlags, boolean create, boolean add) {
5701 final String name = pkg.packageName;
5702 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005703 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704
5705 if (p != null) {
5706 p.pkg = pkg;
5707 }
5708 return p;
5709 }
5710
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005711 PackageSetting peekPackageLP(String name) {
5712 return mPackages.get(name);
5713 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 PackageSetting p = mPackages.get(name);
5715 if (p != null && p.codePath.getPath().equals(codePath)) {
5716 return p;
5717 }
5718 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005719 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 }
5721
5722 void setInstallStatus(String pkgName, int status) {
5723 PackageSetting p = mPackages.get(pkgName);
5724 if(p != null) {
5725 if(p.getInstallStatus() != status) {
5726 p.setInstallStatus(status);
5727 }
5728 }
5729 }
5730
Jacek Surazski65e13172009-04-28 15:26:38 +02005731 void setInstallerPackageName(String pkgName,
5732 String installerPkgName) {
5733 PackageSetting p = mPackages.get(pkgName);
5734 if(p != null) {
5735 p.setInstallerPackageName(installerPkgName);
5736 }
5737 }
5738
5739 String getInstallerPackageName(String pkgName) {
5740 PackageSetting p = mPackages.get(pkgName);
5741 return (p == null) ? null : p.getInstallerPackageName();
5742 }
5743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 int getInstallStatus(String pkgName) {
5745 PackageSetting p = mPackages.get(pkgName);
5746 if(p != null) {
5747 return p.getInstallStatus();
5748 }
5749 return -1;
5750 }
5751
5752 SharedUserSetting getSharedUserLP(String name,
5753 int pkgFlags, boolean create) {
5754 SharedUserSetting s = mSharedUsers.get(name);
5755 if (s == null) {
5756 if (!create) {
5757 return null;
5758 }
5759 s = new SharedUserSetting(name, pkgFlags);
5760 if (MULTIPLE_APPLICATION_UIDS) {
5761 s.userId = newUserIdLP(s);
5762 } else {
5763 s.userId = FIRST_APPLICATION_UID;
5764 }
5765 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
5766 // < 0 means we couldn't assign a userid; fall out and return
5767 // s, which is currently null
5768 if (s.userId >= 0) {
5769 mSharedUsers.put(name, s);
5770 }
5771 }
5772
5773 return s;
5774 }
5775
5776 int disableSystemPackageLP(String name) {
5777 PackageSetting p = mPackages.get(name);
5778 if(p == null) {
5779 Log.w(TAG, "Package:"+name+" is not an installed package");
5780 return -1;
5781 }
5782 PackageSetting dp = mDisabledSysPackages.get(name);
5783 // always make sure the system package code and resource paths dont change
5784 if(dp == null) {
5785 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5786 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5787 }
5788 mDisabledSysPackages.put(name, p);
5789 }
5790 return removePackageLP(name);
5791 }
5792
5793 PackageSetting enableSystemPackageLP(String name) {
5794 PackageSetting p = mDisabledSysPackages.get(name);
5795 if(p == null) {
5796 Log.w(TAG, "Package:"+name+" is not disabled");
5797 return null;
5798 }
5799 // Reset flag in ApplicationInfo object
5800 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
5801 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5802 }
5803 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005804 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 mDisabledSysPackages.remove(name);
5806 return ret;
5807 }
5808
5809 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005810 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 PackageSetting p = mPackages.get(name);
5812 if (p != null) {
5813 if (p.userId == uid) {
5814 return p;
5815 }
5816 reportSettingsProblem(Log.ERROR,
5817 "Adding duplicate package, keeping first: " + name);
5818 return null;
5819 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005820 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 p.userId = uid;
5822 if (addUserIdLP(uid, p, name)) {
5823 mPackages.put(name, p);
5824 return p;
5825 }
5826 return null;
5827 }
5828
5829 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
5830 SharedUserSetting s = mSharedUsers.get(name);
5831 if (s != null) {
5832 if (s.userId == uid) {
5833 return s;
5834 }
5835 reportSettingsProblem(Log.ERROR,
5836 "Adding duplicate shared user, keeping first: " + name);
5837 return null;
5838 }
5839 s = new SharedUserSetting(name, pkgFlags);
5840 s.userId = uid;
5841 if (addUserIdLP(uid, s, name)) {
5842 mSharedUsers.put(name, s);
5843 return s;
5844 }
5845 return null;
5846 }
5847
5848 private PackageSetting getPackageLP(String name,
5849 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005850 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 PackageSetting p = mPackages.get(name);
5852 if (p != null) {
5853 if (!p.codePath.equals(codePath)) {
5854 // Check to see if its a disabled system app
5855 PackageSetting ps = mDisabledSysPackages.get(name);
5856 if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07005857 // This is an updated system app with versions in both system
5858 // and data partition. Just let the most recent version
5859 // take precedence.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 return p;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005861 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07005862 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07005863 reportSettingsProblem(Log.WARN,
5864 "Package " + name + " codePath changed from " + p.codePath
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005865 + " to " + codePath + "; Retaining data and using new code from " +
5866 codePath);
5867 p.codePath = codePath;
5868 p.resourcePath = resourcePath;
5869 p.codePathString = codePath.toString();
5870 p.resourcePathString = resourcePath.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 }
5872 } else if (p.sharedUser != sharedUser) {
5873 reportSettingsProblem(Log.WARN,
5874 "Package " + name + " shared user changed from "
5875 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
5876 + " to "
5877 + (sharedUser != null ? sharedUser.name : "<nothing>")
5878 + "; replacing with new");
5879 p = null;
5880 }
5881 }
5882 if (p == null) {
5883 // Create a new PackageSettings entry. this can end up here because
5884 // of code path mismatch or user id mismatch of an updated system partition
5885 if (!create) {
5886 return null;
5887 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005888 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07005890 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005891 if (sharedUser != null) {
5892 p.userId = sharedUser.userId;
5893 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005894 // Assign new user id
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 p.userId = newUserIdLP(p);
5896 } else {
5897 p.userId = FIRST_APPLICATION_UID;
5898 }
5899 if (p.userId < 0) {
5900 reportSettingsProblem(Log.WARN,
5901 "Package " + name + " could not be assigned a valid uid");
5902 return null;
5903 }
5904 if (add) {
5905 // Finish adding new package by adding it and updating shared
5906 // user preferences
5907 insertPackageSettingLP(p, name, sharedUser);
5908 }
5909 }
5910 return p;
5911 }
5912
5913 // Utility method that adds a PackageSetting to mPackages and
5914 // completes updating the shared user attributes
5915 private void insertPackageSettingLP(PackageSetting p, String name,
5916 SharedUserSetting sharedUser) {
5917 mPackages.put(name, p);
5918 if (sharedUser != null) {
5919 if (p.sharedUser != null && p.sharedUser != sharedUser) {
5920 reportSettingsProblem(Log.ERROR,
5921 "Package " + p.name + " was user "
5922 + p.sharedUser + " but is now " + sharedUser
5923 + "; I am not changing its files so it will probably fail!");
5924 p.sharedUser.packages.remove(p);
5925 } else if (p.userId != sharedUser.userId) {
5926 reportSettingsProblem(Log.ERROR,
5927 "Package " + p.name + " was user id " + p.userId
5928 + " but is now user " + sharedUser
5929 + " with id " + sharedUser.userId
5930 + "; I am not changing its files so it will probably fail!");
5931 }
5932
5933 sharedUser.packages.add(p);
5934 p.sharedUser = sharedUser;
5935 p.userId = sharedUser.userId;
5936 }
5937 }
5938
5939 private void updateSharedUserPerms (PackageSetting deletedPs) {
5940 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
5941 Log.i(TAG, "Trying to update info for null package. Just ignoring");
5942 return;
5943 }
5944 // No sharedUserId
5945 if (deletedPs.sharedUser == null) {
5946 return;
5947 }
5948 SharedUserSetting sus = deletedPs.sharedUser;
5949 // Update permissions
5950 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
5951 boolean used = false;
5952 if (!sus.grantedPermissions.contains (eachPerm)) {
5953 continue;
5954 }
5955 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapub97b8f82009-06-19 15:09:18 -07005956 if (pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 used = true;
5958 break;
5959 }
5960 }
5961 if (!used) {
5962 // can safely delete this permission from list
5963 sus.grantedPermissions.remove(eachPerm);
5964 sus.loadedPermissions.remove(eachPerm);
5965 }
5966 }
5967 // Update gids
5968 int newGids[] = null;
5969 for (PackageSetting pkg:sus.packages) {
5970 newGids = appendInts(newGids, pkg.gids);
5971 }
5972 sus.gids = newGids;
5973 }
5974
5975 private int removePackageLP(String name) {
5976 PackageSetting p = mPackages.get(name);
5977 if (p != null) {
5978 mPackages.remove(name);
5979 if (p.sharedUser != null) {
5980 p.sharedUser.packages.remove(p);
5981 if (p.sharedUser.packages.size() == 0) {
5982 mSharedUsers.remove(p.sharedUser.name);
5983 removeUserIdLP(p.sharedUser.userId);
5984 return p.sharedUser.userId;
5985 }
5986 } else {
5987 removeUserIdLP(p.userId);
5988 return p.userId;
5989 }
5990 }
5991 return -1;
5992 }
5993
5994 private boolean addUserIdLP(int uid, Object obj, Object name) {
5995 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
5996 return false;
5997 }
5998
5999 if (uid >= FIRST_APPLICATION_UID) {
6000 int N = mUserIds.size();
6001 final int index = uid - FIRST_APPLICATION_UID;
6002 while (index >= N) {
6003 mUserIds.add(null);
6004 N++;
6005 }
6006 if (mUserIds.get(index) != null) {
6007 reportSettingsProblem(Log.ERROR,
6008 "Adding duplicate shared id: " + uid
6009 + " name=" + name);
6010 return false;
6011 }
6012 mUserIds.set(index, obj);
6013 } else {
6014 if (mOtherUserIds.get(uid) != null) {
6015 reportSettingsProblem(Log.ERROR,
6016 "Adding duplicate shared id: " + uid
6017 + " name=" + name);
6018 return false;
6019 }
6020 mOtherUserIds.put(uid, obj);
6021 }
6022 return true;
6023 }
6024
6025 public Object getUserIdLP(int uid) {
6026 if (uid >= FIRST_APPLICATION_UID) {
6027 int N = mUserIds.size();
6028 final int index = uid - FIRST_APPLICATION_UID;
6029 return index < N ? mUserIds.get(index) : null;
6030 } else {
6031 return mOtherUserIds.get(uid);
6032 }
6033 }
6034
6035 private void removeUserIdLP(int uid) {
6036 if (uid >= FIRST_APPLICATION_UID) {
6037 int N = mUserIds.size();
6038 final int index = uid - FIRST_APPLICATION_UID;
6039 if (index < N) mUserIds.set(index, null);
6040 } else {
6041 mOtherUserIds.remove(uid);
6042 }
6043 }
6044
6045 void writeLP() {
6046 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6047
6048 // Keep the old settings around until we know the new ones have
6049 // been successfully written.
6050 if (mSettingsFilename.exists()) {
6051 if (mBackupSettingsFilename.exists()) {
6052 mBackupSettingsFilename.delete();
6053 }
6054 mSettingsFilename.renameTo(mBackupSettingsFilename);
6055 }
6056
6057 mPastSignatures.clear();
6058
6059 try {
6060 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6061
6062 //XmlSerializer serializer = XmlUtils.serializerInstance();
6063 XmlSerializer serializer = new FastXmlSerializer();
6064 serializer.setOutput(str, "utf-8");
6065 serializer.startDocument(null, true);
6066 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6067
6068 serializer.startTag(null, "packages");
6069
6070 serializer.startTag(null, "permission-trees");
6071 for (BasePermission bp : mPermissionTrees.values()) {
6072 writePermission(serializer, bp);
6073 }
6074 serializer.endTag(null, "permission-trees");
6075
6076 serializer.startTag(null, "permissions");
6077 for (BasePermission bp : mPermissions.values()) {
6078 writePermission(serializer, bp);
6079 }
6080 serializer.endTag(null, "permissions");
6081
6082 for (PackageSetting pkg : mPackages.values()) {
6083 writePackage(serializer, pkg);
6084 }
6085
6086 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6087 writeDisabledSysPackage(serializer, pkg);
6088 }
6089
6090 serializer.startTag(null, "preferred-packages");
6091 int N = mPreferredPackages.size();
6092 for (int i=0; i<N; i++) {
6093 PackageSetting pkg = mPreferredPackages.get(i);
6094 serializer.startTag(null, "item");
6095 serializer.attribute(null, "name", pkg.name);
6096 serializer.endTag(null, "item");
6097 }
6098 serializer.endTag(null, "preferred-packages");
6099
6100 serializer.startTag(null, "preferred-activities");
6101 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6102 serializer.startTag(null, "item");
6103 pa.writeToXml(serializer);
6104 serializer.endTag(null, "item");
6105 }
6106 serializer.endTag(null, "preferred-activities");
6107
6108 for (SharedUserSetting usr : mSharedUsers.values()) {
6109 serializer.startTag(null, "shared-user");
6110 serializer.attribute(null, "name", usr.name);
6111 serializer.attribute(null, "userId",
6112 Integer.toString(usr.userId));
6113 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6114 serializer.startTag(null, "perms");
6115 for (String name : usr.grantedPermissions) {
6116 serializer.startTag(null, "item");
6117 serializer.attribute(null, "name", name);
6118 serializer.endTag(null, "item");
6119 }
6120 serializer.endTag(null, "perms");
6121 serializer.endTag(null, "shared-user");
6122 }
6123
6124 serializer.endTag(null, "packages");
6125
6126 serializer.endDocument();
6127
6128 str.flush();
6129 str.close();
6130
6131 // New settings successfully written, old ones are no longer
6132 // needed.
6133 mBackupSettingsFilename.delete();
6134 FileUtils.setPermissions(mSettingsFilename.toString(),
6135 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6136 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6137 |FileUtils.S_IROTH,
6138 -1, -1);
6139
6140 } catch(XmlPullParserException e) {
6141 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
6142
6143 } catch(java.io.IOException e) {
6144 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
6145
6146 }
6147
6148 //Debug.stopMethodTracing();
6149 }
6150
6151 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
6152 throws java.io.IOException {
6153 serializer.startTag(null, "updated-package");
6154 serializer.attribute(null, "name", pkg.name);
6155 serializer.attribute(null, "codePath", pkg.codePathString);
6156 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006157 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006158 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6159 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6160 }
6161 if (pkg.sharedUser == null) {
6162 serializer.attribute(null, "userId",
6163 Integer.toString(pkg.userId));
6164 } else {
6165 serializer.attribute(null, "sharedUserId",
6166 Integer.toString(pkg.userId));
6167 }
6168 serializer.startTag(null, "perms");
6169 if (pkg.sharedUser == null) {
6170 // If this is a shared user, the permissions will
6171 // be written there. We still need to write an
6172 // empty permissions list so permissionsFixed will
6173 // be set.
6174 for (final String name : pkg.grantedPermissions) {
6175 BasePermission bp = mPermissions.get(name);
6176 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6177 // We only need to write signature or system permissions but this wont
6178 // match the semantics of grantedPermissions. So write all permissions.
6179 serializer.startTag(null, "item");
6180 serializer.attribute(null, "name", name);
6181 serializer.endTag(null, "item");
6182 }
6183 }
6184 }
6185 serializer.endTag(null, "perms");
6186 serializer.endTag(null, "updated-package");
6187 }
6188
6189 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
6190 throws java.io.IOException {
6191 serializer.startTag(null, "package");
6192 serializer.attribute(null, "name", pkg.name);
6193 serializer.attribute(null, "codePath", pkg.codePathString);
6194 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6195 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6196 }
6197 serializer.attribute(null, "system",
6198 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6199 ? "true" : "false");
6200 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006201 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 if (pkg.sharedUser == null) {
6203 serializer.attribute(null, "userId",
6204 Integer.toString(pkg.userId));
6205 } else {
6206 serializer.attribute(null, "sharedUserId",
6207 Integer.toString(pkg.userId));
6208 }
6209 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6210 serializer.attribute(null, "enabled",
6211 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6212 ? "true" : "false");
6213 }
6214 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6215 serializer.attribute(null, "installStatus", "false");
6216 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006217 if (pkg.installerPackageName != null) {
6218 serializer.attribute(null, "installer", pkg.installerPackageName);
6219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6221 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6222 serializer.startTag(null, "perms");
6223 if (pkg.sharedUser == null) {
6224 // If this is a shared user, the permissions will
6225 // be written there. We still need to write an
6226 // empty permissions list so permissionsFixed will
6227 // be set.
6228 for (final String name : pkg.grantedPermissions) {
6229 serializer.startTag(null, "item");
6230 serializer.attribute(null, "name", name);
6231 serializer.endTag(null, "item");
6232 }
6233 }
6234 serializer.endTag(null, "perms");
6235 }
6236 if (pkg.disabledComponents.size() > 0) {
6237 serializer.startTag(null, "disabled-components");
6238 for (final String name : pkg.disabledComponents) {
6239 serializer.startTag(null, "item");
6240 serializer.attribute(null, "name", name);
6241 serializer.endTag(null, "item");
6242 }
6243 serializer.endTag(null, "disabled-components");
6244 }
6245 if (pkg.enabledComponents.size() > 0) {
6246 serializer.startTag(null, "enabled-components");
6247 for (final String name : pkg.enabledComponents) {
6248 serializer.startTag(null, "item");
6249 serializer.attribute(null, "name", name);
6250 serializer.endTag(null, "item");
6251 }
6252 serializer.endTag(null, "enabled-components");
6253 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 serializer.endTag(null, "package");
6256 }
6257
6258 void writePermission(XmlSerializer serializer, BasePermission bp)
6259 throws XmlPullParserException, java.io.IOException {
6260 if (bp.type != BasePermission.TYPE_BUILTIN
6261 && bp.sourcePackage != null) {
6262 serializer.startTag(null, "item");
6263 serializer.attribute(null, "name", bp.name);
6264 serializer.attribute(null, "package", bp.sourcePackage);
6265 if (DEBUG_SETTINGS) Log.v(TAG,
6266 "Writing perm: name=" + bp.name + " type=" + bp.type);
6267 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6268 PermissionInfo pi = bp.perm != null ? bp.perm.info
6269 : bp.pendingInfo;
6270 if (pi != null) {
6271 serializer.attribute(null, "type", "dynamic");
6272 if (pi.icon != 0) {
6273 serializer.attribute(null, "icon",
6274 Integer.toString(pi.icon));
6275 }
6276 if (pi.nonLocalizedLabel != null) {
6277 serializer.attribute(null, "label",
6278 pi.nonLocalizedLabel.toString());
6279 }
6280 if (pi.protectionLevel !=
6281 PermissionInfo.PROTECTION_NORMAL) {
6282 serializer.attribute(null, "protection",
6283 Integer.toString(pi.protectionLevel));
6284 }
6285 }
6286 }
6287 serializer.endTag(null, "item");
6288 }
6289 }
6290
6291 String getReadMessagesLP() {
6292 return mReadMessages.toString();
6293 }
6294
6295 ArrayList<String> getListOfIncompleteInstallPackages() {
6296 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6297 Iterator<String> its = kList.iterator();
6298 ArrayList<String> ret = new ArrayList<String>();
6299 while(its.hasNext()) {
6300 String key = its.next();
6301 PackageSetting ps = mPackages.get(key);
6302 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6303 ret.add(key);
6304 }
6305 }
6306 return ret;
6307 }
6308
6309 boolean readLP() {
6310 FileInputStream str = null;
6311 if (mBackupSettingsFilename.exists()) {
6312 try {
6313 str = new FileInputStream(mBackupSettingsFilename);
6314 mReadMessages.append("Reading from backup settings file\n");
6315 Log.i(TAG, "Reading from backup settings file!");
6316 } catch (java.io.IOException e) {
6317 // We'll try for the normal settings file.
6318 }
6319 }
6320
6321 mPastSignatures.clear();
6322
6323 try {
6324 if (str == null) {
6325 if (!mSettingsFilename.exists()) {
6326 mReadMessages.append("No settings file found\n");
6327 Log.i(TAG, "No current settings file!");
6328 return false;
6329 }
6330 str = new FileInputStream(mSettingsFilename);
6331 }
6332 XmlPullParser parser = Xml.newPullParser();
6333 parser.setInput(str, null);
6334
6335 int type;
6336 while ((type=parser.next()) != XmlPullParser.START_TAG
6337 && type != XmlPullParser.END_DOCUMENT) {
6338 ;
6339 }
6340
6341 if (type != XmlPullParser.START_TAG) {
6342 mReadMessages.append("No start tag found in settings file\n");
6343 Log.e(TAG, "No start tag found in package manager settings");
6344 return false;
6345 }
6346
6347 int outerDepth = parser.getDepth();
6348 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6349 && (type != XmlPullParser.END_TAG
6350 || parser.getDepth() > outerDepth)) {
6351 if (type == XmlPullParser.END_TAG
6352 || type == XmlPullParser.TEXT) {
6353 continue;
6354 }
6355
6356 String tagName = parser.getName();
6357 if (tagName.equals("package")) {
6358 readPackageLP(parser);
6359 } else if (tagName.equals("permissions")) {
6360 readPermissionsLP(mPermissions, parser);
6361 } else if (tagName.equals("permission-trees")) {
6362 readPermissionsLP(mPermissionTrees, parser);
6363 } else if (tagName.equals("shared-user")) {
6364 readSharedUserLP(parser);
6365 } else if (tagName.equals("preferred-packages")) {
6366 readPreferredPackagesLP(parser);
6367 } else if (tagName.equals("preferred-activities")) {
6368 readPreferredActivitiesLP(parser);
6369 } else if(tagName.equals("updated-package")) {
6370 readDisabledSysPackageLP(parser);
6371 } else {
6372 Log.w(TAG, "Unknown element under <packages>: "
6373 + parser.getName());
6374 XmlUtils.skipCurrentTag(parser);
6375 }
6376 }
6377
6378 str.close();
6379
6380 } catch(XmlPullParserException e) {
6381 mReadMessages.append("Error reading: " + e.toString());
6382 Log.e(TAG, "Error reading package manager settings", e);
6383
6384 } catch(java.io.IOException e) {
6385 mReadMessages.append("Error reading: " + e.toString());
6386 Log.e(TAG, "Error reading package manager settings", e);
6387
6388 }
6389
6390 int N = mPendingPackages.size();
6391 for (int i=0; i<N; i++) {
6392 final PendingPackage pp = mPendingPackages.get(i);
6393 Object idObj = getUserIdLP(pp.sharedId);
6394 if (idObj != null && idObj instanceof SharedUserSetting) {
6395 PackageSetting p = getPackageLP(pp.name,
6396 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006397 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 if (p == null) {
6399 Log.w(TAG, "Unable to create application package for "
6400 + pp.name);
6401 continue;
6402 }
6403 p.copyFrom(pp);
6404 } else if (idObj != null) {
6405 String msg = "Bad package setting: package " + pp.name
6406 + " has shared uid " + pp.sharedId
6407 + " that is not a shared uid\n";
6408 mReadMessages.append(msg);
6409 Log.e(TAG, msg);
6410 } else {
6411 String msg = "Bad package setting: package " + pp.name
6412 + " has shared uid " + pp.sharedId
6413 + " that is not defined\n";
6414 mReadMessages.append(msg);
6415 Log.e(TAG, msg);
6416 }
6417 }
6418 mPendingPackages.clear();
6419
6420 N = mPendingPreferredPackages.size();
6421 mPreferredPackages.clear();
6422 for (int i=0; i<N; i++) {
6423 final String name = mPendingPreferredPackages.get(i);
6424 final PackageSetting p = mPackages.get(name);
6425 if (p != null) {
6426 mPreferredPackages.add(p);
6427 } else {
6428 Log.w(TAG, "Unknown preferred package: " + name);
6429 }
6430 }
6431 mPendingPreferredPackages.clear();
6432
6433 mReadMessages.append("Read completed successfully: "
6434 + mPackages.size() + " packages, "
6435 + mSharedUsers.size() + " shared uids\n");
6436
6437 return true;
6438 }
6439
6440 private int readInt(XmlPullParser parser, String ns, String name,
6441 int defValue) {
6442 String v = parser.getAttributeValue(ns, name);
6443 try {
6444 if (v == null) {
6445 return defValue;
6446 }
6447 return Integer.parseInt(v);
6448 } catch (NumberFormatException e) {
6449 reportSettingsProblem(Log.WARN,
6450 "Error in package manager settings: attribute " +
6451 name + " has bad integer value " + v + " at "
6452 + parser.getPositionDescription());
6453 }
6454 return defValue;
6455 }
6456
6457 private void readPermissionsLP(HashMap<String, BasePermission> out,
6458 XmlPullParser parser)
6459 throws IOException, XmlPullParserException {
6460 int outerDepth = parser.getDepth();
6461 int type;
6462 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6463 && (type != XmlPullParser.END_TAG
6464 || parser.getDepth() > outerDepth)) {
6465 if (type == XmlPullParser.END_TAG
6466 || type == XmlPullParser.TEXT) {
6467 continue;
6468 }
6469
6470 String tagName = parser.getName();
6471 if (tagName.equals("item")) {
6472 String name = parser.getAttributeValue(null, "name");
6473 String sourcePackage = parser.getAttributeValue(null, "package");
6474 String ptype = parser.getAttributeValue(null, "type");
6475 if (name != null && sourcePackage != null) {
6476 boolean dynamic = "dynamic".equals(ptype);
6477 BasePermission bp = new BasePermission(name, sourcePackage,
6478 dynamic
6479 ? BasePermission.TYPE_DYNAMIC
6480 : BasePermission.TYPE_NORMAL);
6481 if (dynamic) {
6482 PermissionInfo pi = new PermissionInfo();
6483 pi.packageName = sourcePackage.intern();
6484 pi.name = name.intern();
6485 pi.icon = readInt(parser, null, "icon", 0);
6486 pi.nonLocalizedLabel = parser.getAttributeValue(
6487 null, "label");
6488 pi.protectionLevel = readInt(parser, null, "protection",
6489 PermissionInfo.PROTECTION_NORMAL);
6490 bp.pendingInfo = pi;
6491 }
6492 out.put(bp.name, bp);
6493 } else {
6494 reportSettingsProblem(Log.WARN,
6495 "Error in package manager settings: permissions has"
6496 + " no name at " + parser.getPositionDescription());
6497 }
6498 } else {
6499 reportSettingsProblem(Log.WARN,
6500 "Unknown element reading permissions: "
6501 + parser.getName() + " at "
6502 + parser.getPositionDescription());
6503 }
6504 XmlUtils.skipCurrentTag(parser);
6505 }
6506 }
6507
6508 private void readDisabledSysPackageLP(XmlPullParser parser)
6509 throws XmlPullParserException, IOException {
6510 String name = parser.getAttributeValue(null, "name");
6511 String codePathStr = parser.getAttributeValue(null, "codePath");
6512 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6513 if(resourcePathStr == null) {
6514 resourcePathStr = codePathStr;
6515 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006516 String version = parser.getAttributeValue(null, "version");
6517 int versionCode = 0;
6518 if (version != null) {
6519 try {
6520 versionCode = Integer.parseInt(version);
6521 } catch (NumberFormatException e) {
6522 }
6523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524
6525 int pkgFlags = 0;
6526 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6527 PackageSetting ps = new PackageSetting(name,
6528 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006529 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 String timeStampStr = parser.getAttributeValue(null, "ts");
6531 if (timeStampStr != null) {
6532 try {
6533 long timeStamp = Long.parseLong(timeStampStr);
6534 ps.setTimeStamp(timeStamp, timeStampStr);
6535 } catch (NumberFormatException e) {
6536 }
6537 }
6538 String idStr = parser.getAttributeValue(null, "userId");
6539 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6540 if(ps.userId <= 0) {
6541 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6542 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6543 }
6544 int outerDepth = parser.getDepth();
6545 int type;
6546 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6547 && (type != XmlPullParser.END_TAG
6548 || parser.getDepth() > outerDepth)) {
6549 if (type == XmlPullParser.END_TAG
6550 || type == XmlPullParser.TEXT) {
6551 continue;
6552 }
6553
6554 String tagName = parser.getName();
6555 if (tagName.equals("perms")) {
6556 readGrantedPermissionsLP(parser,
6557 ps.grantedPermissions);
6558 } else {
6559 reportSettingsProblem(Log.WARN,
6560 "Unknown element under <updated-package>: "
6561 + parser.getName());
6562 XmlUtils.skipCurrentTag(parser);
6563 }
6564 }
6565 mDisabledSysPackages.put(name, ps);
6566 }
6567
6568 private void readPackageLP(XmlPullParser parser)
6569 throws XmlPullParserException, IOException {
6570 String name = null;
6571 String idStr = null;
6572 String sharedIdStr = null;
6573 String codePathStr = null;
6574 String resourcePathStr = null;
6575 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02006576 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006577 int pkgFlags = 0;
6578 String timeStampStr;
6579 long timeStamp = 0;
6580 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006581 String version = null;
6582 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 try {
6584 name = parser.getAttributeValue(null, "name");
6585 idStr = parser.getAttributeValue(null, "userId");
6586 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6587 codePathStr = parser.getAttributeValue(null, "codePath");
6588 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006589 version = parser.getAttributeValue(null, "version");
6590 if (version != null) {
6591 try {
6592 versionCode = Integer.parseInt(version);
6593 } catch (NumberFormatException e) {
6594 }
6595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006596 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02006597 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006598 if (systemStr != null) {
6599 if ("true".equals(systemStr)) {
6600 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6601 }
6602 } else {
6603 // Old settings that don't specify system... just treat
6604 // them as system, good enough.
6605 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6606 }
6607 timeStampStr = parser.getAttributeValue(null, "ts");
6608 if (timeStampStr != null) {
6609 try {
6610 timeStamp = Long.parseLong(timeStampStr);
6611 } catch (NumberFormatException e) {
6612 }
6613 }
6614 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
6615 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
6616 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6617 if (resourcePathStr == null) {
6618 resourcePathStr = codePathStr;
6619 }
6620 if (name == null) {
6621 reportSettingsProblem(Log.WARN,
6622 "Error in package manager settings: <package> has no name at "
6623 + parser.getPositionDescription());
6624 } else if (codePathStr == null) {
6625 reportSettingsProblem(Log.WARN,
6626 "Error in package manager settings: <package> has no codePath at "
6627 + parser.getPositionDescription());
6628 } else if (userId > 0) {
6629 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006630 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6632 + ": userId=" + userId + " pkg=" + packageSetting);
6633 if (packageSetting == null) {
6634 reportSettingsProblem(Log.ERROR,
6635 "Failure adding uid " + userId
6636 + " while parsing settings at "
6637 + parser.getPositionDescription());
6638 } else {
6639 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6640 }
6641 } else if (sharedIdStr != null) {
6642 userId = sharedIdStr != null
6643 ? Integer.parseInt(sharedIdStr) : 0;
6644 if (userId > 0) {
6645 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006646 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 packageSetting.setTimeStamp(timeStamp, timeStampStr);
6648 mPendingPackages.add((PendingPackage) packageSetting);
6649 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
6650 + ": sharedUserId=" + userId + " pkg="
6651 + packageSetting);
6652 } else {
6653 reportSettingsProblem(Log.WARN,
6654 "Error in package manager settings: package "
6655 + name + " has bad sharedId " + sharedIdStr
6656 + " at " + parser.getPositionDescription());
6657 }
6658 } else {
6659 reportSettingsProblem(Log.WARN,
6660 "Error in package manager settings: package "
6661 + name + " has bad userId " + idStr + " at "
6662 + parser.getPositionDescription());
6663 }
6664 } catch (NumberFormatException e) {
6665 reportSettingsProblem(Log.WARN,
6666 "Error in package manager settings: package "
6667 + name + " has bad userId " + idStr + " at "
6668 + parser.getPositionDescription());
6669 }
6670 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02006671 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006672 final String enabledStr = parser.getAttributeValue(null, "enabled");
6673 if (enabledStr != null) {
6674 if (enabledStr.equalsIgnoreCase("true")) {
6675 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
6676 } else if (enabledStr.equalsIgnoreCase("false")) {
6677 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
6678 } else if (enabledStr.equalsIgnoreCase("default")) {
6679 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6680 } else {
6681 reportSettingsProblem(Log.WARN,
6682 "Error in package manager settings: package "
6683 + name + " has bad enabled value: " + idStr
6684 + " at " + parser.getPositionDescription());
6685 }
6686 } else {
6687 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6688 }
6689 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
6690 if (installStatusStr != null) {
6691 if (installStatusStr.equalsIgnoreCase("false")) {
6692 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
6693 } else {
6694 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
6695 }
6696 }
6697
6698 int outerDepth = parser.getDepth();
6699 int type;
6700 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6701 && (type != XmlPullParser.END_TAG
6702 || parser.getDepth() > outerDepth)) {
6703 if (type == XmlPullParser.END_TAG
6704 || type == XmlPullParser.TEXT) {
6705 continue;
6706 }
6707
6708 String tagName = parser.getName();
6709 if (tagName.equals("disabled-components")) {
6710 readDisabledComponentsLP(packageSetting, parser);
6711 } else if (tagName.equals("enabled-components")) {
6712 readEnabledComponentsLP(packageSetting, parser);
6713 } else if (tagName.equals("sigs")) {
6714 packageSetting.signatures.readXml(parser, mPastSignatures);
6715 } else if (tagName.equals("perms")) {
6716 readGrantedPermissionsLP(parser,
6717 packageSetting.loadedPermissions);
6718 packageSetting.permissionsFixed = true;
6719 } else {
6720 reportSettingsProblem(Log.WARN,
6721 "Unknown element under <package>: "
6722 + parser.getName());
6723 XmlUtils.skipCurrentTag(parser);
6724 }
6725 }
6726 } else {
6727 XmlUtils.skipCurrentTag(parser);
6728 }
6729 }
6730
6731 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
6732 XmlPullParser parser)
6733 throws IOException, XmlPullParserException {
6734 int outerDepth = parser.getDepth();
6735 int type;
6736 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6737 && (type != XmlPullParser.END_TAG
6738 || parser.getDepth() > outerDepth)) {
6739 if (type == XmlPullParser.END_TAG
6740 || type == XmlPullParser.TEXT) {
6741 continue;
6742 }
6743
6744 String tagName = parser.getName();
6745 if (tagName.equals("item")) {
6746 String name = parser.getAttributeValue(null, "name");
6747 if (name != null) {
6748 packageSetting.disabledComponents.add(name.intern());
6749 } else {
6750 reportSettingsProblem(Log.WARN,
6751 "Error in package manager settings: <disabled-components> has"
6752 + " no name at " + parser.getPositionDescription());
6753 }
6754 } else {
6755 reportSettingsProblem(Log.WARN,
6756 "Unknown element under <disabled-components>: "
6757 + parser.getName());
6758 }
6759 XmlUtils.skipCurrentTag(parser);
6760 }
6761 }
6762
6763 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
6764 XmlPullParser parser)
6765 throws IOException, XmlPullParserException {
6766 int outerDepth = parser.getDepth();
6767 int type;
6768 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6769 && (type != XmlPullParser.END_TAG
6770 || parser.getDepth() > outerDepth)) {
6771 if (type == XmlPullParser.END_TAG
6772 || type == XmlPullParser.TEXT) {
6773 continue;
6774 }
6775
6776 String tagName = parser.getName();
6777 if (tagName.equals("item")) {
6778 String name = parser.getAttributeValue(null, "name");
6779 if (name != null) {
6780 packageSetting.enabledComponents.add(name.intern());
6781 } else {
6782 reportSettingsProblem(Log.WARN,
6783 "Error in package manager settings: <enabled-components> has"
6784 + " no name at " + parser.getPositionDescription());
6785 }
6786 } else {
6787 reportSettingsProblem(Log.WARN,
6788 "Unknown element under <enabled-components>: "
6789 + parser.getName());
6790 }
6791 XmlUtils.skipCurrentTag(parser);
6792 }
6793 }
6794
6795 private void readSharedUserLP(XmlPullParser parser)
6796 throws XmlPullParserException, IOException {
6797 String name = null;
6798 String idStr = null;
6799 int pkgFlags = 0;
6800 SharedUserSetting su = null;
6801 try {
6802 name = parser.getAttributeValue(null, "name");
6803 idStr = parser.getAttributeValue(null, "userId");
6804 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
6805 if ("true".equals(parser.getAttributeValue(null, "system"))) {
6806 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6807 }
6808 if (name == null) {
6809 reportSettingsProblem(Log.WARN,
6810 "Error in package manager settings: <shared-user> has no name at "
6811 + parser.getPositionDescription());
6812 } else if (userId == 0) {
6813 reportSettingsProblem(Log.WARN,
6814 "Error in package manager settings: shared-user "
6815 + name + " has bad userId " + idStr + " at "
6816 + parser.getPositionDescription());
6817 } else {
6818 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
6819 reportSettingsProblem(Log.ERROR,
6820 "Occurred while parsing settings at "
6821 + parser.getPositionDescription());
6822 }
6823 }
6824 } catch (NumberFormatException e) {
6825 reportSettingsProblem(Log.WARN,
6826 "Error in package manager settings: package "
6827 + name + " has bad userId " + idStr + " at "
6828 + parser.getPositionDescription());
6829 };
6830
6831 if (su != null) {
6832 int outerDepth = parser.getDepth();
6833 int type;
6834 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6835 && (type != XmlPullParser.END_TAG
6836 || parser.getDepth() > outerDepth)) {
6837 if (type == XmlPullParser.END_TAG
6838 || type == XmlPullParser.TEXT) {
6839 continue;
6840 }
6841
6842 String tagName = parser.getName();
6843 if (tagName.equals("sigs")) {
6844 su.signatures.readXml(parser, mPastSignatures);
6845 } else if (tagName.equals("perms")) {
6846 readGrantedPermissionsLP(parser, su.loadedPermissions);
6847 } else {
6848 reportSettingsProblem(Log.WARN,
6849 "Unknown element under <shared-user>: "
6850 + parser.getName());
6851 XmlUtils.skipCurrentTag(parser);
6852 }
6853 }
6854
6855 } else {
6856 XmlUtils.skipCurrentTag(parser);
6857 }
6858 }
6859
6860 private void readGrantedPermissionsLP(XmlPullParser parser,
6861 HashSet<String> outPerms) throws IOException, XmlPullParserException {
6862 int outerDepth = parser.getDepth();
6863 int type;
6864 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6865 && (type != XmlPullParser.END_TAG
6866 || parser.getDepth() > outerDepth)) {
6867 if (type == XmlPullParser.END_TAG
6868 || type == XmlPullParser.TEXT) {
6869 continue;
6870 }
6871
6872 String tagName = parser.getName();
6873 if (tagName.equals("item")) {
6874 String name = parser.getAttributeValue(null, "name");
6875 if (name != null) {
6876 outPerms.add(name.intern());
6877 } else {
6878 reportSettingsProblem(Log.WARN,
6879 "Error in package manager settings: <perms> has"
6880 + " no name at " + parser.getPositionDescription());
6881 }
6882 } else {
6883 reportSettingsProblem(Log.WARN,
6884 "Unknown element under <perms>: "
6885 + parser.getName());
6886 }
6887 XmlUtils.skipCurrentTag(parser);
6888 }
6889 }
6890
6891 private void readPreferredPackagesLP(XmlPullParser parser)
6892 throws XmlPullParserException, IOException {
6893 int outerDepth = parser.getDepth();
6894 int type;
6895 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6896 && (type != XmlPullParser.END_TAG
6897 || parser.getDepth() > outerDepth)) {
6898 if (type == XmlPullParser.END_TAG
6899 || type == XmlPullParser.TEXT) {
6900 continue;
6901 }
6902
6903 String tagName = parser.getName();
6904 if (tagName.equals("item")) {
6905 String name = parser.getAttributeValue(null, "name");
6906 if (name != null) {
6907 mPendingPreferredPackages.add(name);
6908 } else {
6909 reportSettingsProblem(Log.WARN,
6910 "Error in package manager settings: <preferred-package> has no name at "
6911 + parser.getPositionDescription());
6912 }
6913 } else {
6914 reportSettingsProblem(Log.WARN,
6915 "Unknown element under <preferred-packages>: "
6916 + parser.getName());
6917 }
6918 XmlUtils.skipCurrentTag(parser);
6919 }
6920 }
6921
6922 private void readPreferredActivitiesLP(XmlPullParser parser)
6923 throws XmlPullParserException, IOException {
6924 int outerDepth = parser.getDepth();
6925 int type;
6926 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6927 && (type != XmlPullParser.END_TAG
6928 || parser.getDepth() > outerDepth)) {
6929 if (type == XmlPullParser.END_TAG
6930 || type == XmlPullParser.TEXT) {
6931 continue;
6932 }
6933
6934 String tagName = parser.getName();
6935 if (tagName.equals("item")) {
6936 PreferredActivity pa = new PreferredActivity(parser);
6937 if (pa.mParseError == null) {
6938 mPreferredActivities.addFilter(pa);
6939 } else {
6940 reportSettingsProblem(Log.WARN,
6941 "Error in package manager settings: <preferred-activity> "
6942 + pa.mParseError + " at "
6943 + parser.getPositionDescription());
6944 }
6945 } else {
6946 reportSettingsProblem(Log.WARN,
6947 "Unknown element under <preferred-activities>: "
6948 + parser.getName());
6949 XmlUtils.skipCurrentTag(parser);
6950 }
6951 }
6952 }
6953
6954 // Returns -1 if we could not find an available UserId to assign
6955 private int newUserIdLP(Object obj) {
6956 // Let's be stupidly inefficient for now...
6957 final int N = mUserIds.size();
6958 for (int i=0; i<N; i++) {
6959 if (mUserIds.get(i) == null) {
6960 mUserIds.set(i, obj);
6961 return FIRST_APPLICATION_UID + i;
6962 }
6963 }
6964
6965 // None left?
6966 if (N >= MAX_APPLICATION_UIDS) {
6967 return -1;
6968 }
6969
6970 mUserIds.add(obj);
6971 return FIRST_APPLICATION_UID + N;
6972 }
6973
6974 public PackageSetting getDisabledSystemPkg(String name) {
6975 synchronized(mPackages) {
6976 PackageSetting ps = mDisabledSysPackages.get(name);
6977 return ps;
6978 }
6979 }
6980
6981 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
6982 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
6983 if (Config.LOGV) {
6984 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
6985 + " componentName = " + componentInfo.name);
6986 Log.v(TAG, "enabledComponents: "
6987 + Arrays.toString(packageSettings.enabledComponents.toArray()));
6988 Log.v(TAG, "disabledComponents: "
6989 + Arrays.toString(packageSettings.disabledComponents.toArray()));
6990 }
6991 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
6992 || ((componentInfo.enabled
6993 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
6994 || (componentInfo.applicationInfo.enabled
6995 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
6996 && !packageSettings.disabledComponents.contains(componentInfo.name))
6997 || packageSettings.enabledComponents.contains(componentInfo.name));
6998 }
6999 }
7000}