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