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