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