blob: c000d8a53e9e937fcdcf6d1a10945ee113599b77 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
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;
29import android.content.ComponentName;
30import android.content.ContentResolver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.content.pm.ActivityInfo;
35import android.content.pm.ApplicationInfo;
36import android.content.pm.ComponentInfo;
37import android.content.pm.IPackageDataObserver;
38import android.content.pm.IPackageDeleteObserver;
39import android.content.pm.IPackageInstallObserver;
40import android.content.pm.IPackageManager;
41import android.content.pm.IPackageStatsObserver;
42import android.content.pm.InstrumentationInfo;
43import android.content.pm.PackageInfo;
44import android.content.pm.PackageManager;
45import android.content.pm.PackageStats;
46import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
47import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
48import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
49import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
50import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
51import android.content.pm.PackageParser;
52import android.content.pm.PermissionInfo;
53import android.content.pm.PermissionGroupInfo;
54import android.content.pm.ProviderInfo;
55import android.content.pm.ResolveInfo;
56import android.content.pm.ServiceInfo;
57import android.content.pm.Signature;
58import android.net.Uri;
59import android.os.Binder;
60import android.os.Bundle;
61import android.os.HandlerThread;
62import android.os.Parcel;
63import android.os.RemoteException;
64import android.os.Environment;
65import android.os.FileObserver;
66import android.os.FileUtils;
67import android.os.Handler;
68import android.os.ParcelFileDescriptor;
69import android.os.Process;
70import android.os.ServiceManager;
71import android.os.SystemClock;
72import android.os.SystemProperties;
73import android.util.*;
74import android.view.Display;
75import android.view.WindowManager;
76
77import java.io.File;
78import java.io.FileDescriptor;
79import java.io.FileInputStream;
80import java.io.FileNotFoundException;
81import java.io.FileOutputStream;
82import java.io.FileReader;
83import java.io.FilenameFilter;
84import java.io.IOException;
85import java.io.InputStream;
86import java.io.PrintWriter;
87import java.util.ArrayList;
88import java.util.Arrays;
89import java.util.Collections;
90import java.util.Comparator;
91import java.util.Enumeration;
92import java.util.HashMap;
93import java.util.HashSet;
94import java.util.Iterator;
95import java.util.List;
96import java.util.Map;
97import java.util.zip.ZipEntry;
98import java.util.zip.ZipFile;
99import java.util.zip.ZipOutputStream;
100
101class PackageManagerService extends IPackageManager.Stub {
102 private static final String TAG = "PackageManager";
103 private static final boolean DEBUG_SETTINGS = false;
104 private static final boolean DEBUG_PREFERRED = false;
105
106 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
107 private static final int RADIO_UID = Process.PHONE_UID;
108 private static final int FIRST_APPLICATION_UID =
109 Process.FIRST_APPLICATION_UID;
110 private static final int MAX_APPLICATION_UIDS = 1000;
111
112 private static final boolean SHOW_INFO = false;
113
114 private static final boolean GET_CERTIFICATES = true;
115
116 private static final int REMOVE_EVENTS =
117 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
118 private static final int ADD_EVENTS =
119 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
120
121 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
122
123 static final int SCAN_MONITOR = 1<<0;
124 static final int SCAN_NO_DEX = 1<<1;
125 static final int SCAN_FORCE_DEX = 1<<2;
126 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
127 static final int SCAN_FORWARD_LOCKED = 1<<4;
128
129 static final int LOG_BOOT_PROGRESS_PMS_START = 3060;
130 static final int LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START = 3070;
131 static final int LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START = 3080;
132 static final int LOG_BOOT_PROGRESS_PMS_SCAN_END = 3090;
133 static final int LOG_BOOT_PROGRESS_PMS_READY = 3100;
134
135 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
136 Process.THREAD_PRIORITY_BACKGROUND);
137 final Handler mHandler;
138
139 final int mSdkVersion = SystemProperties.getInt(
140 "ro.build.version.sdk", 0);
141
142 final Context mContext;
143 final boolean mFactoryTest;
144 final DisplayMetrics mMetrics;
145 final int mDefParseFlags;
146 final String[] mSeparateProcesses;
147
148 // This is where all application persistent data goes.
149 final File mAppDataDir;
150
151 // This is the object monitoring the framework dir.
152 final FileObserver mFrameworkInstallObserver;
153
154 // This is the object monitoring the system app dir.
155 final FileObserver mSystemInstallObserver;
156
157 // This is the object monitoring mAppInstallDir.
158 final FileObserver mAppInstallObserver;
159
160 // This is the object monitoring mDrmAppPrivateInstallDir.
161 final FileObserver mDrmAppInstallObserver;
162
163 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
164 // LOCK HELD. Can be called with mInstallLock held.
165 final Installer mInstaller;
166
167 final File mFrameworkDir;
168 final File mSystemAppDir;
169 final File mAppInstallDir;
170
171 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
172 // apps.
173 final File mDrmAppPrivateInstallDir;
174
175 // ----------------------------------------------------------------
176
177 // Lock for state used when installing and doing other long running
178 // operations. Methods that must be called with this lock held have
179 // the prefix "LI".
180 Object mInstallLock = new Object();
181
182 // These are the directories in the 3rd party applications installed dir
183 // that we have currently loaded packages from. Keys are the application's
184 // installed zip file (absolute codePath), and values are Package.
185 final HashMap<String, PackageParser.Package> mAppDirs =
186 new HashMap<String, PackageParser.Package>();
187
188 // Information for the parser to write more useful error messages.
189 File mScanningPath;
190 int mLastScanError;
191
192 final int[] mOutPermissions = new int[3];
193
194 // ----------------------------------------------------------------
195
196 // Keys are String (package name), values are Package. This also serves
197 // as the lock for the global state. Methods that must be called with
198 // this lock held have the prefix "LP".
199 final HashMap<String, PackageParser.Package> mPackages =
200 new HashMap<String, PackageParser.Package>();
201
202 final Settings mSettings;
203 boolean mRestoredSettings;
204 boolean mReportedUidError;
205
206 // Group-ids that are given to all packages as read from etc/permissions.xml.
207 int[] mGlobalGids;
208
209 // These are the built-in uid -> permission mappings that were read from the
210 // etc/permissions.xml file.
211 final SparseArray<HashSet<String>> mSystemPermissions =
212 new SparseArray<HashSet<String>>();
213
214 // These are the built-in shared libraries that were read from the
215 // etc/permissions.xml file.
216 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
217
218 // All available activities, for your resolving pleasure.
219 final ActivityIntentResolver mActivities =
220 new ActivityIntentResolver();
221
222 // All available receivers, for your resolving pleasure.
223 final ActivityIntentResolver mReceivers =
224 new ActivityIntentResolver();
225
226 // All available services, for your resolving pleasure.
227 final ServiceIntentResolver mServices = new ServiceIntentResolver();
228
229 // Keys are String (provider class name), values are Provider.
230 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
231 new HashMap<ComponentName, PackageParser.Provider>();
232
233 // Mapping from provider base names (first directory in content URI codePath)
234 // to the provider information.
235 final HashMap<String, PackageParser.Provider> mProviders =
236 new HashMap<String, PackageParser.Provider>();
237
238 // Mapping from instrumentation class names to info about them.
239 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
240 new HashMap<ComponentName, PackageParser.Instrumentation>();
241
242 // Mapping from permission names to info about them.
243 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
244 new HashMap<String, PackageParser.PermissionGroup>();
245
246 boolean mSystemReady;
247 boolean mSafeMode;
248 boolean mHasSystemUidErrors;
249
250 ApplicationInfo mAndroidApplication;
251 final ActivityInfo mResolveActivity = new ActivityInfo();
252 final ResolveInfo mResolveInfo = new ResolveInfo();
253 ComponentName mResolveComponentName;
254 PackageParser.Package mPlatformPackage;
255
256 public static final IPackageManager main(Context context, boolean factoryTest) {
257 PackageManagerService m = new PackageManagerService(context, factoryTest);
258 ServiceManager.addService("package", m);
259 return m;
260 }
261
262 static String[] splitString(String str, char sep) {
263 int count = 1;
264 int i = 0;
265 while ((i=str.indexOf(sep, i)) >= 0) {
266 count++;
267 i++;
268 }
269
270 String[] res = new String[count];
271 i=0;
272 count = 0;
273 int lastI=0;
274 while ((i=str.indexOf(sep, i)) >= 0) {
275 res[count] = str.substring(lastI, i);
276 count++;
277 i++;
278 lastI = i;
279 }
280 res[count] = str.substring(lastI, str.length());
281 return res;
282 }
283
284 public PackageManagerService(Context context, boolean factoryTest) {
285 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
286 SystemClock.uptimeMillis());
287
288 if (mSdkVersion <= 0) {
289 Log.w(TAG, "**** ro.build.version.sdk not set!");
290 }
291
292 mContext = context;
293 mFactoryTest = factoryTest;
294 mMetrics = new DisplayMetrics();
295 mSettings = new Settings();
296 mSettings.addSharedUserLP("android.uid.system",
297 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
298 mSettings.addSharedUserLP("android.uid.phone",
299 MULTIPLE_APPLICATION_UIDS
300 ? RADIO_UID : FIRST_APPLICATION_UID,
301 ApplicationInfo.FLAG_SYSTEM);
302
303 String separateProcesses = SystemProperties.get("debug.separate_processes");
304 if (separateProcesses != null && separateProcesses.length() > 0) {
305 if ("*".equals(separateProcesses)) {
306 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
307 mSeparateProcesses = null;
308 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
309 } else {
310 mDefParseFlags = 0;
311 mSeparateProcesses = separateProcesses.split(",");
312 Log.w(TAG, "Running with debug.separate_processes: "
313 + separateProcesses);
314 }
315 } else {
316 mDefParseFlags = 0;
317 mSeparateProcesses = null;
318 }
319
320 Installer installer = new Installer();
321 // Little hacky thing to check if installd is here, to determine
322 // whether we are running on the simulator and thus need to take
323 // care of building the /data file structure ourself.
324 // (apparently the sim now has a working installer)
325 if (installer.ping() && Process.supportsProcesses()) {
326 mInstaller = installer;
327 } else {
328 mInstaller = null;
329 }
330
331 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
332 Display d = wm.getDefaultDisplay();
333 d.getMetrics(mMetrics);
334
335 synchronized (mInstallLock) {
336 synchronized (mPackages) {
337 mHandlerThread.start();
338 mHandler = new Handler(mHandlerThread.getLooper());
339
340 File dataDir = Environment.getDataDirectory();
341 mAppDataDir = new File(dataDir, "data");
342 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
343
344 if (mInstaller == null) {
345 // Make sure these dirs exist, when we are running in
346 // the simulator.
347 // Make a wide-open directory for random misc stuff.
348 File miscDir = new File(dataDir, "misc");
349 miscDir.mkdirs();
350 mAppDataDir.mkdirs();
351 mDrmAppPrivateInstallDir.mkdirs();
352 }
353
354 readPermissions();
355
356 mRestoredSettings = mSettings.readLP();
357 long startTime = SystemClock.uptimeMillis();
358
359 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
360 startTime);
361
362 int scanMode = SCAN_MONITOR;
363
364 final HashSet<String> libFiles = new HashSet<String>();
365
366 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
367
368 if (mInstaller != null) {
369 /**
370 * Out of paranoia, ensure that everything in the boot class
371 * path has been dexed.
372 */
373 String bootClassPath = System.getProperty("java.boot.class.path");
374 if (bootClassPath != null) {
375 String[] paths = splitString(bootClassPath, ':');
376 for (int i=0; i<paths.length; i++) {
377 try {
378 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
379 libFiles.add(paths[i]);
380 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
381 }
382 } catch (FileNotFoundException e) {
383 Log.w(TAG, "Boot class path not found: " + paths[i]);
384 } catch (IOException e) {
385 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
386 }
387 }
388 } else {
389 Log.w(TAG, "No BOOTCLASSPATH found!");
390 }
391
392 /**
393 * Also ensure all external libraries have had dexopt run on them.
394 */
395 if (mSharedLibraries.size() > 0) {
396 Iterator<String> libs = mSharedLibraries.values().iterator();
397 while (libs.hasNext()) {
398 String lib = libs.next();
399 try {
400 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
401 libFiles.add(lib);
402 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
403 }
404 } catch (FileNotFoundException e) {
405 Log.w(TAG, "Library not found: " + lib);
406 } catch (IOException e) {
407 Log.w(TAG, "Exception reading library: " + lib, e);
408 }
409 }
410 }
411
412 // Gross hack for now: we know this file doesn't contain any
413 // code, so don't dexopt it to avoid the resulting log spew.
414 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
415
416 /**
417 * And there are a number of commands implemented in Java, which
418 * we currently need to do the dexopt on so that they can be
419 * run from a non-root shell.
420 */
421 String[] frameworkFiles = mFrameworkDir.list();
422 if (frameworkFiles != null && mInstaller != null) {
423 for (int i=0; i<frameworkFiles.length; i++) {
424 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
425 String path = libPath.getPath();
426 // Skip the file if we alrady did it.
427 if (libFiles.contains(path)) {
428 continue;
429 }
430 // Skip the file if it is not a type we want to dexopt.
431 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
432 continue;
433 }
434 try {
435 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
436 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
437 }
438 } catch (FileNotFoundException e) {
439 Log.w(TAG, "Jar not found: " + path);
440 } catch (IOException e) {
441 Log.w(TAG, "Exception reading jar: " + path, e);
442 }
443 }
444 }
445 }
446
447 mFrameworkInstallObserver = new AppDirObserver(
448 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
449 mFrameworkInstallObserver.startWatching();
450 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
451 scanMode | SCAN_NO_DEX);
452 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
453 mSystemInstallObserver = new AppDirObserver(
454 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
455 mSystemInstallObserver.startWatching();
456 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
457 mAppInstallDir = new File(dataDir, "app");
458 if (mInstaller == null) {
459 // Make sure these dirs exist, when we are running in
460 // the simulator.
461 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
462 }
463 //look for any incomplete package installations
464 ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
465 //clean up list
466 for(int i = 0; i < deletePkgsList.size(); i++) {
467 //clean up here
468 cleanupInstallFailedPackage(deletePkgsList.get(i));
469 }
470 //delete tmp files
471 deleteTempPackageFiles();
472
473 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
474 SystemClock.uptimeMillis());
475 mAppInstallObserver = new AppDirObserver(
476 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
477 mAppInstallObserver.startWatching();
478 scanDirLI(mAppInstallDir, 0, scanMode);
479
480 mDrmAppInstallObserver = new AppDirObserver(
481 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
482 mDrmAppInstallObserver.startWatching();
483 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode);
484
485 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
486 SystemClock.uptimeMillis());
487 Log.i(TAG, "Time to scan packages: "
488 + ((SystemClock.uptimeMillis()-startTime)/1000f)
489 + " seconds");
490
491 updatePermissionsLP();
492
493 mSettings.writeLP();
494
495 EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
496 SystemClock.uptimeMillis());
497
498 // Now after opening every single application zip, make sure they
499 // are all flushed. Not really needed, but keeps things nice and
500 // tidy.
501 Runtime.getRuntime().gc();
502 } // synchronized (mPackages)
503 } // synchronized (mInstallLock)
504 }
505
506 @Override
507 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
508 throws RemoteException {
509 try {
510 return super.onTransact(code, data, reply, flags);
511 } catch (RuntimeException e) {
512 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
513 Log.e(TAG, "Package Manager Crash", e);
514 }
515 throw e;
516 }
517 }
518
519 void cleanupInstallFailedPackage(String packageName) {
520 if (mInstaller != null) {
521 int retCode = mInstaller.remove(packageName);
522 if (retCode < 0) {
523 Log.w(TAG, "Couldn't remove app data directory for package: "
524 + packageName + ", retcode=" + retCode);
525 }
526 } else {
527 //for emulator
528 PackageParser.Package pkg = mPackages.get(packageName);
529 File dataDir = new File(pkg.applicationInfo.dataDir);
530 dataDir.delete();
531 }
532 mSettings.removePackageLP(packageName);
533 }
534
535 void readPermissions() {
536 final File permFile = new File(Environment.getRootDirectory(),
537 "etc/permissions.xml");
538 FileReader permReader = null;
539 try {
540 permReader = new FileReader(permFile);
541 } catch (FileNotFoundException e) {
542 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
543 return;
544 }
545
546 try {
547 XmlPullParser parser = Xml.newPullParser();
548 parser.setInput(permReader);
549
550 XmlUtils.beginDocument(parser, "permissions");
551
552 while (true) {
553 XmlUtils.nextElement(parser);
554 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
555 break;
556 }
557
558 String name = parser.getName();
559 if ("group".equals(name)) {
560 String gidStr = parser.getAttributeValue(null, "gid");
561 if (gidStr != null) {
562 int gid = Integer.parseInt(gidStr);
563 mGlobalGids = appendInt(mGlobalGids, gid);
564 } else {
565 Log.w(TAG, "<group> without gid at "
566 + parser.getPositionDescription());
567 }
568 XmlUtils.skipCurrentTag(parser);
569 continue;
570
571 } else if ("permission".equals(name)) {
572 String perm = parser.getAttributeValue(null, "name");
573 if (perm == null) {
574 Log.w(TAG, "<permission> without name at "
575 + parser.getPositionDescription());
576 XmlUtils.skipCurrentTag(parser);
577 continue;
578 }
579 perm = perm.intern();
580 readPermission(parser, perm);
581
582 } else if ("assign-permission".equals(name)) {
583 String perm = parser.getAttributeValue(null, "name");
584 if (perm == null) {
585 Log.w(TAG, "<assign-permission> without name at "
586 + parser.getPositionDescription());
587 XmlUtils.skipCurrentTag(parser);
588 continue;
589 }
590 String uidStr = parser.getAttributeValue(null, "uid");
591 if (uidStr == null) {
592 Log.w(TAG, "<assign-permission> without uid at "
593 + parser.getPositionDescription());
594 XmlUtils.skipCurrentTag(parser);
595 continue;
596 }
597 int uid = Process.getUidForName(uidStr);
598 if (uid < 0) {
599 Log.w(TAG, "<assign-permission> with unknown uid \""
600 + uidStr + "\" at "
601 + parser.getPositionDescription());
602 XmlUtils.skipCurrentTag(parser);
603 continue;
604 }
605 perm = perm.intern();
606 HashSet<String> perms = mSystemPermissions.get(uid);
607 if (perms == null) {
608 perms = new HashSet<String>();
609 mSystemPermissions.put(uid, perms);
610 }
611 perms.add(perm);
612 XmlUtils.skipCurrentTag(parser);
613
614 } else if ("library".equals(name)) {
615 String lname = parser.getAttributeValue(null, "name");
616 String lfile = parser.getAttributeValue(null, "file");
617 if (lname == null) {
618 Log.w(TAG, "<library> without name at "
619 + parser.getPositionDescription());
620 } else if (lfile == null) {
621 Log.w(TAG, "<library> without file at "
622 + parser.getPositionDescription());
623 } else {
624 this.mSharedLibraries.put(lname, lfile);
625 }
626 XmlUtils.skipCurrentTag(parser);
627 continue;
628
629 } else {
630 XmlUtils.skipCurrentTag(parser);
631 continue;
632 }
633
634 }
635 } catch (XmlPullParserException e) {
636 Log.w(TAG, "Got execption parsing permissions.", e);
637 } catch (IOException e) {
638 Log.w(TAG, "Got execption parsing permissions.", e);
639 }
640 }
641
642 void readPermission(XmlPullParser parser, String name)
643 throws IOException, XmlPullParserException {
644
645 name = name.intern();
646
647 BasePermission bp = mSettings.mPermissions.get(name);
648 if (bp == null) {
649 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
650 mSettings.mPermissions.put(name, bp);
651 }
652 int outerDepth = parser.getDepth();
653 int type;
654 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
655 && (type != XmlPullParser.END_TAG
656 || parser.getDepth() > outerDepth)) {
657 if (type == XmlPullParser.END_TAG
658 || type == XmlPullParser.TEXT) {
659 continue;
660 }
661
662 String tagName = parser.getName();
663 if ("group".equals(tagName)) {
664 String gidStr = parser.getAttributeValue(null, "gid");
665 if (gidStr != null) {
666 int gid = Process.getGidForName(gidStr);
667 bp.gids = appendInt(bp.gids, gid);
668 } else {
669 Log.w(TAG, "<group> without gid at "
670 + parser.getPositionDescription());
671 }
672 }
673 XmlUtils.skipCurrentTag(parser);
674 }
675 }
676
677 int[] appendInt(int[] cur, int val) {
678 if (cur == null) {
679 return new int[] { val };
680 }
681 final int N = cur.length;
682 for (int i=0; i<N; i++) {
683 if (cur[i] == val) {
684 return cur;
685 }
686 }
687 int[] ret = new int[N+1];
688 System.arraycopy(cur, 0, ret, 0, N);
689 ret[N] = val;
690 return ret;
691 }
692
693 int[] appendInts(int[] cur, int[] add) {
694 if (add == null) return cur;
695 if (cur == null) return add;
696 final int N = add.length;
697 for (int i=0; i<N; i++) {
698 cur = appendInt(cur, add[i]);
699 }
700 return cur;
701 }
702
703 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
704 final PackageSetting ps = (PackageSetting)p.mExtras;
705 if (ps == null) {
706 return null;
707 }
708 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
709 return PackageParser.generatePackageInfo(p, gp.gids, flags);
710 }
711
712 public PackageInfo getPackageInfo(String packageName, int flags) {
713 synchronized (mPackages) {
714 PackageParser.Package p = mPackages.get(packageName);
715 if (Config.LOGV) Log.v(
716 TAG, "getApplicationInfo " + packageName
717 + ": " + p);
718 if (p != null) {
719 return generatePackageInfo(p, flags);
720 }
721 }
722 return null;
723 }
724
725 public int getPackageUid(String packageName) {
726 synchronized (mPackages) {
727 PackageParser.Package p = mPackages.get(packageName);
728 return p != null ? p.applicationInfo.uid : -1;
729 }
730 }
731
732 public int[] getPackageGids(String packageName) {
733 synchronized (mPackages) {
734 PackageParser.Package p = mPackages.get(packageName);
735 if (Config.LOGV) Log.v(
736 TAG, "getApplicationInfo " + packageName
737 + ": " + p);
738 if (p != null) {
739 final PackageSetting ps = (PackageSetting)p.mExtras;
740 final SharedUserSetting suid = ps.sharedUser;
741 return suid != null ? suid.gids : ps.gids;
742 }
743 }
744 // stupid thing to indicate an error.
745 return new int[0];
746 }
747
748 public PermissionInfo getPermissionInfo(String name, int flags) {
749 synchronized (mPackages) {
750 final BasePermission p = mSettings.mPermissions.get(name);
751 if (p != null && p.perm != null) {
752 return PackageParser.generatePermissionInfo(p.perm, flags);
753 }
754 return null;
755 }
756 }
757
758 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
759 synchronized (mPackages) {
760 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
761 for (BasePermission p : mSettings.mPermissions.values()) {
762 if (group == null) {
763 if (p.perm.info.group == null) {
764 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
765 }
766 } else {
767 if (group.equals(p.perm.info.group)) {
768 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
769 }
770 }
771 }
772
773 if (out.size() > 0) {
774 return out;
775 }
776 return mPermissionGroups.containsKey(group) ? out : null;
777 }
778 }
779
780 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
781 synchronized (mPackages) {
782 return PackageParser.generatePermissionGroupInfo(
783 mPermissionGroups.get(name), flags);
784 }
785 }
786
787 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
788 synchronized (mPackages) {
789 final int N = mPermissionGroups.size();
790 ArrayList<PermissionGroupInfo> out
791 = new ArrayList<PermissionGroupInfo>(N);
792 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
793 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
794 }
795 return out;
796 }
797 }
798
799 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
800 synchronized (mPackages) {
801 PackageParser.Package p = mPackages.get(packageName);
802 if (Config.LOGV) Log.v(
803 TAG, "getApplicationInfo " + packageName
804 + ": " + p);
805 if (p != null) {
806 // Note: isEnabledLP() does not apply here - always return info
807 return PackageParser.generateApplicationInfo(p, flags);
808 }
809 if ("android".equals(packageName)||"system".equals(packageName)) {
810 return mAndroidApplication;
811 }
812 }
813 return null;
814 }
815
816 public void freeApplicationCache(final long freeStorageSize, final IPackageDataObserver observer) {
817 mContext.enforceCallingOrSelfPermission(
818 android.Manifest.permission.CLEAR_APP_CACHE, null);
819 // Queue up an async operation since clearing cache may take a little while.
820 mHandler.post(new Runnable() {
821 public void run() {
822 mHandler.removeCallbacks(this);
823 boolean succeded = true;
824 if (mInstaller != null) {
825 int retCode = mInstaller.freeCache(freeStorageSize);
826 if (retCode < 0) {
827 Log.w(TAG, "Couldn't clear application caches");
828 succeded = false;
829 }
830 } //end if mInstaller
831 if(observer != null) {
832 try {
833 observer.onRemoveCompleted(null, succeded);
834 } catch (RemoteException e) {
835 Log.i(TAG, "Observer no longer exists.");
836 }
837 } //end if observer
838 } //end run
839 });
840 }
841
842 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
843 synchronized (mPackages) {
844 PackageParser.Activity a = mActivities.mActivities.get(component);
845 if (Config.LOGV) Log.v(
846 TAG, "getActivityInfo " + component + ": " + a);
847 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
848 return PackageParser.generateActivityInfo(a, flags);
849 }
850 if (mResolveComponentName.equals(component)) {
851 return mResolveActivity;
852 }
853 }
854 return null;
855 }
856
857 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
858 synchronized (mPackages) {
859 PackageParser.Activity a = mReceivers.mActivities.get(component);
860 if (Config.LOGV) Log.v(
861 TAG, "getReceiverInfo " + component + ": " + a);
862 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
863 return PackageParser.generateActivityInfo(a, flags);
864 }
865 }
866 return null;
867 }
868
869 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
870 synchronized (mPackages) {
871 PackageParser.Service s = mServices.mServices.get(component);
872 if (Config.LOGV) Log.v(
873 TAG, "getServiceInfo " + component + ": " + s);
874 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
875 return PackageParser.generateServiceInfo(s, flags);
876 }
877 }
878 return null;
879 }
880
881 public int checkPermission(String permName, String pkgName) {
882 synchronized (mPackages) {
883 PackageParser.Package p = mPackages.get(pkgName);
884 if (p != null && p.mExtras != null) {
885 PackageSetting ps = (PackageSetting)p.mExtras;
886 if (ps.sharedUser != null) {
887 if (ps.sharedUser.grantedPermissions.contains(permName)) {
888 return PackageManager.PERMISSION_GRANTED;
889 }
890 } else if (ps.grantedPermissions.contains(permName)) {
891 return PackageManager.PERMISSION_GRANTED;
892 }
893 }
894 }
895 return PackageManager.PERMISSION_DENIED;
896 }
897
898 public int checkUidPermission(String permName, int uid) {
899 synchronized (mPackages) {
900 Object obj = mSettings.getUserIdLP(uid);
901 if (obj != null) {
902 if (obj instanceof SharedUserSetting) {
903 SharedUserSetting sus = (SharedUserSetting)obj;
904 if (sus.grantedPermissions.contains(permName)) {
905 return PackageManager.PERMISSION_GRANTED;
906 }
907 } else if (obj instanceof PackageSetting) {
908 PackageSetting ps = (PackageSetting)obj;
909 if (ps.grantedPermissions.contains(permName)) {
910 return PackageManager.PERMISSION_GRANTED;
911 }
912 }
913 } else {
914 HashSet<String> perms = mSystemPermissions.get(uid);
915 if (perms != null && perms.contains(permName)) {
916 return PackageManager.PERMISSION_GRANTED;
917 }
918 }
919 }
920 return PackageManager.PERMISSION_DENIED;
921 }
922
923 private BasePermission findPermissionTreeLP(String permName) {
924 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
925 if (permName.startsWith(bp.name) &&
926 permName.length() > bp.name.length() &&
927 permName.charAt(bp.name.length()) == '.') {
928 return bp;
929 }
930 }
931 return null;
932 }
933
934 private BasePermission checkPermissionTreeLP(String permName) {
935 if (permName != null) {
936 BasePermission bp = findPermissionTreeLP(permName);
937 if (bp != null) {
938 if (bp.uid == Binder.getCallingUid()) {
939 return bp;
940 }
941 throw new SecurityException("Calling uid "
942 + Binder.getCallingUid()
943 + " is not allowed to add to permission tree "
944 + bp.name + " owned by uid " + bp.uid);
945 }
946 }
947 throw new SecurityException("No permission tree found for " + permName);
948 }
949
950 public boolean addPermission(PermissionInfo info) {
951 synchronized (mPackages) {
952 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
953 throw new SecurityException("Label must be specified in permission");
954 }
955 BasePermission tree = checkPermissionTreeLP(info.name);
956 BasePermission bp = mSettings.mPermissions.get(info.name);
957 boolean added = bp == null;
958 if (added) {
959 bp = new BasePermission(info.name, tree.sourcePackage,
960 BasePermission.TYPE_DYNAMIC);
961 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
962 throw new SecurityException(
963 "Not allowed to modify non-dynamic permission "
964 + info.name);
965 }
966 bp.perm = new PackageParser.Permission(tree.perm.owner,
967 new PermissionInfo(info));
968 bp.perm.info.packageName = tree.perm.info.packageName;
969 bp.uid = tree.uid;
970 if (added) {
971 mSettings.mPermissions.put(info.name, bp);
972 }
973 mSettings.writeLP();
974 return added;
975 }
976 }
977
978 public void removePermission(String name) {
979 synchronized (mPackages) {
980 checkPermissionTreeLP(name);
981 BasePermission bp = mSettings.mPermissions.get(name);
982 if (bp != null) {
983 if (bp.type != BasePermission.TYPE_DYNAMIC) {
984 throw new SecurityException(
985 "Not allowed to modify non-dynamic permission "
986 + name);
987 }
988 mSettings.mPermissions.remove(name);
989 mSettings.writeLP();
990 }
991 }
992 }
993
994 public int checkSignatures(String pkg1, String pkg2) {
995 synchronized (mPackages) {
996 PackageParser.Package p1 = mPackages.get(pkg1);
997 PackageParser.Package p2 = mPackages.get(pkg2);
998 if (p1 == null || p1.mExtras == null
999 || p2 == null || p2.mExtras == null) {
1000 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1001 }
1002 return checkSignaturesLP(p1, p2);
1003 }
1004 }
1005
1006 int checkSignaturesLP(PackageParser.Package p1, PackageParser.Package p2) {
1007 if (p1.mSignatures == null) {
1008 return p2.mSignatures == null
1009 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1010 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1011 }
1012 if (p2.mSignatures == null) {
1013 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1014 }
1015 final int N1 = p1.mSignatures.length;
1016 final int N2 = p2.mSignatures.length;
1017 for (int i=0; i<N1; i++) {
1018 boolean match = false;
1019 for (int j=0; j<N2; j++) {
1020 if (p1.mSignatures[i].equals(p2.mSignatures[j])) {
1021 match = true;
1022 break;
1023 }
1024 }
1025 if (!match) {
1026 return PackageManager.SIGNATURE_NO_MATCH;
1027 }
1028 }
1029 return PackageManager.SIGNATURE_MATCH;
1030 }
1031
1032 public String[] getPackagesForUid(int uid) {
1033 synchronized (mPackages) {
1034 Object obj = mSettings.getUserIdLP(uid);
1035 if (obj instanceof SharedUserSetting) {
1036 SharedUserSetting sus = (SharedUserSetting)obj;
1037 final int N = sus.packages.size();
1038 String[] res = new String[N];
1039 Iterator<PackageSetting> it = sus.packages.iterator();
1040 int i=0;
1041 while (it.hasNext()) {
1042 res[i++] = it.next().name;
1043 }
1044 return res;
1045 } else if (obj instanceof PackageSetting) {
1046 PackageSetting ps = (PackageSetting)obj;
1047 return new String[] { ps.name };
1048 }
1049 }
1050 return null;
1051 }
1052
1053 public String getNameForUid(int uid) {
1054 synchronized (mPackages) {
1055 Object obj = mSettings.getUserIdLP(uid);
1056 if (obj instanceof SharedUserSetting) {
1057 SharedUserSetting sus = (SharedUserSetting)obj;
1058 return sus.name + ":" + sus.userId;
1059 } else if (obj instanceof PackageSetting) {
1060 PackageSetting ps = (PackageSetting)obj;
1061 return ps.name;
1062 }
1063 }
1064 return null;
1065 }
1066
1067 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1068 int flags) {
1069 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
1070 if (query != null) {
1071 final int N = query.size();
1072 if (N == 1) {
1073 return query.get(0);
1074 } else if (N > 1) {
1075 // If there is more than one activity with the same priority,
1076 // then let the user decide between them.
1077 ResolveInfo r0 = query.get(0);
1078 ResolveInfo r1 = query.get(1);
1079 if (false) {
1080 System.out.println(r0.activityInfo.name +
1081 "=" + r0.priority + " vs " +
1082 r1.activityInfo.name +
1083 "=" + r1.priority);
1084 }
1085 // If the first activity has a higher priority, or a different
1086 // default, then it is always desireable to pick it.
1087 if (r0.priority != r1.priority
1088 || r0.preferredOrder != r1.preferredOrder
1089 || r0.isDefault != r1.isDefault) {
1090 return query.get(0);
1091 }
1092 // If we have saved a preference for a preferred activity for
1093 // this Intent, use that.
1094 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1095 flags, query, r0.priority);
1096 if (ri != null) {
1097 return ri;
1098 }
1099 return mResolveInfo;
1100 }
1101 }
1102 return null;
1103 }
1104
1105 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1106 int flags, List<ResolveInfo> query, int priority) {
1107 synchronized (mPackages) {
1108 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1109 List<PreferredActivity> prefs =
1110 mSettings.mPreferredActivities.queryIntent(null,
1111 intent, resolvedType,
1112 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1113 if (prefs != null && prefs.size() > 0) {
1114 // First figure out how good the original match set is.
1115 // We will only allow preferred activities that came
1116 // from the same match quality.
1117 int match = 0;
1118 final int N = query.size();
1119 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1120 for (int j=0; j<N; j++) {
1121 ResolveInfo ri = query.get(j);
1122 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1123 + ": 0x" + Integer.toHexString(match));
1124 if (ri.match > match) match = ri.match;
1125 }
1126 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1127 + Integer.toHexString(match));
1128 match &= IntentFilter.MATCH_CATEGORY_MASK;
1129 final int M = prefs.size();
1130 for (int i=0; i<M; i++) {
1131 PreferredActivity pa = prefs.get(i);
1132 if (pa.mMatch != match) {
1133 continue;
1134 }
1135 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1136 if (DEBUG_PREFERRED) {
1137 Log.v(TAG, "Got preferred activity:");
1138 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1139 }
1140 if (ai != null) {
1141 for (int j=0; j<N; j++) {
1142 ResolveInfo ri = query.get(j);
1143 if (!ri.activityInfo.applicationInfo.packageName
1144 .equals(ai.applicationInfo.packageName)) {
1145 continue;
1146 }
1147 if (!ri.activityInfo.name.equals(ai.name)) {
1148 continue;
1149 }
1150
1151 // Okay we found a previously set preferred app.
1152 // If the result set is different from when this
1153 // was created, we need to clear it and re-ask the
1154 // user their preference.
1155 if (!pa.sameSet(query, priority)) {
1156 Log.i(TAG, "Result set changed, dropping preferred activity for "
1157 + intent + " type " + resolvedType);
1158 mSettings.mPreferredActivities.removeFilter(pa);
1159 return null;
1160 }
1161
1162 // Yay!
1163 return ri;
1164 }
1165 }
1166 }
1167 }
1168 }
1169 return null;
1170 }
1171
1172 public List<ResolveInfo> queryIntentActivities(Intent intent,
1173 String resolvedType, int flags) {
1174 ComponentName comp = intent.getComponent();
1175 if (comp != null) {
1176 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1177 ActivityInfo ai = getActivityInfo(comp, flags);
1178 if (ai != null) {
1179 ResolveInfo ri = new ResolveInfo();
1180 ri.activityInfo = ai;
1181 list.add(ri);
1182 }
1183 return list;
1184 }
1185
1186 synchronized (mPackages) {
1187 return (List<ResolveInfo>)mActivities.
1188 queryIntent(null, intent, resolvedType, flags);
1189 }
1190 }
1191
1192 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1193 Intent[] specifics, String[] specificTypes, Intent intent,
1194 String resolvedType, int flags) {
1195 final String resultsAction = intent.getAction();
1196
1197 List<ResolveInfo> results = queryIntentActivities(
1198 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1199 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1200
1201 int specificsPos = 0;
1202 int N;
1203
1204 // todo: note that the algorithm used here is O(N^2). This
1205 // isn't a problem in our current environment, but if we start running
1206 // into situations where we have more than 5 or 10 matches then this
1207 // should probably be changed to something smarter...
1208
1209 // First we go through and resolve each of the specific items
1210 // that were supplied, taking care of removing any corresponding
1211 // duplicate items in the generic resolve list.
1212 if (specifics != null) {
1213 for (int i=0; i<specifics.length; i++) {
1214 final Intent sintent = specifics[i];
1215 if (sintent == null) {
1216 continue;
1217 }
1218
1219 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1220 String action = sintent.getAction();
1221 if (resultsAction != null && resultsAction.equals(action)) {
1222 // If this action was explicitly requested, then don't
1223 // remove things that have it.
1224 action = null;
1225 }
1226 ComponentName comp = sintent.getComponent();
1227 ResolveInfo ri = null;
1228 ActivityInfo ai = null;
1229 if (comp == null) {
1230 ri = resolveIntent(
1231 sintent,
1232 specificTypes != null ? specificTypes[i] : null,
1233 flags);
1234 if (ri == null) {
1235 continue;
1236 }
1237 if (ri == mResolveInfo) {
1238 // ACK! Must do something better with this.
1239 }
1240 ai = ri.activityInfo;
1241 comp = new ComponentName(ai.applicationInfo.packageName,
1242 ai.name);
1243 } else {
1244 ai = getActivityInfo(comp, flags);
1245 if (ai == null) {
1246 continue;
1247 }
1248 }
1249
1250 // Look for any generic query activities that are duplicates
1251 // of this specific one, and remove them from the results.
1252 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1253 N = results.size();
1254 int j;
1255 for (j=specificsPos; j<N; j++) {
1256 ResolveInfo sri = results.get(j);
1257 if ((sri.activityInfo.name.equals(comp.getClassName())
1258 && sri.activityInfo.applicationInfo.packageName.equals(
1259 comp.getPackageName()))
1260 || (action != null && sri.filter.matchAction(action))) {
1261 results.remove(j);
1262 if (Config.LOGV) Log.v(
1263 TAG, "Removing duplicate item from " + j
1264 + " due to specific " + specificsPos);
1265 if (ri == null) {
1266 ri = sri;
1267 }
1268 j--;
1269 N--;
1270 }
1271 }
1272
1273 // Add this specific item to its proper place.
1274 if (ri == null) {
1275 ri = new ResolveInfo();
1276 ri.activityInfo = ai;
1277 }
1278 results.add(specificsPos, ri);
1279 ri.specificIndex = i;
1280 specificsPos++;
1281 }
1282 }
1283
1284 // Now we go through the remaining generic results and remove any
1285 // duplicate actions that are found here.
1286 N = results.size();
1287 for (int i=specificsPos; i<N-1; i++) {
1288 final ResolveInfo rii = results.get(i);
1289 if (rii.filter == null) {
1290 continue;
1291 }
1292
1293 // Iterate over all of the actions of this result's intent
1294 // filter... typically this should be just one.
1295 final Iterator<String> it = rii.filter.actionsIterator();
1296 if (it == null) {
1297 continue;
1298 }
1299 while (it.hasNext()) {
1300 final String action = it.next();
1301 if (resultsAction != null && resultsAction.equals(action)) {
1302 // If this action was explicitly requested, then don't
1303 // remove things that have it.
1304 continue;
1305 }
1306 for (int j=i+1; j<N; j++) {
1307 final ResolveInfo rij = results.get(j);
1308 if (rij.filter != null && rij.filter.hasAction(action)) {
1309 results.remove(j);
1310 if (Config.LOGV) Log.v(
1311 TAG, "Removing duplicate item from " + j
1312 + " due to action " + action + " at " + i);
1313 j--;
1314 N--;
1315 }
1316 }
1317 }
1318
1319 // If the caller didn't request filter information, drop it now
1320 // so we don't have to marshall/unmarshall it.
1321 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1322 rii.filter = null;
1323 }
1324 }
1325
1326 // Filter out the caller activity if so requested.
1327 if (caller != null) {
1328 N = results.size();
1329 for (int i=0; i<N; i++) {
1330 ActivityInfo ainfo = results.get(i).activityInfo;
1331 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1332 && caller.getClassName().equals(ainfo.name)) {
1333 results.remove(i);
1334 break;
1335 }
1336 }
1337 }
1338
1339 // If the caller didn't request filter information,
1340 // drop them now so we don't have to
1341 // marshall/unmarshall it.
1342 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1343 N = results.size();
1344 for (int i=0; i<N; i++) {
1345 results.get(i).filter = null;
1346 }
1347 }
1348
1349 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1350 return results;
1351 }
1352
1353 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1354 String resolvedType, int flags) {
1355 synchronized (mPackages) {
1356 return (List<ResolveInfo>)mReceivers.
1357 queryIntent(null, intent, resolvedType, flags);
1358 }
1359 }
1360
1361 public ResolveInfo resolveService(Intent intent, String resolvedType,
1362 int flags) {
1363 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1364 flags);
1365 if (query != null) {
1366 if (query.size() >= 1) {
1367 // If there is more than one service with the same priority,
1368 // just arbitrarily pick the first one.
1369 return query.get(0);
1370 }
1371 }
1372 return null;
1373 }
1374
1375 public List<ResolveInfo> queryIntentServices(Intent intent,
1376 String resolvedType, int flags) {
1377 ComponentName comp = intent.getComponent();
1378 if (comp != null) {
1379 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1380 ServiceInfo si = getServiceInfo(comp, flags);
1381 if (si != null) {
1382 ResolveInfo ri = new ResolveInfo();
1383 ri.serviceInfo = si;
1384 list.add(ri);
1385 }
1386 return list;
1387 }
1388
1389 synchronized (mPackages) {
1390 return (List<ResolveInfo>)mServices.
1391 queryIntent(null, intent, resolvedType, flags);
1392 }
1393 }
1394
1395 public List<PackageInfo> getInstalledPackages(int flags) {
1396 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1397
1398 synchronized (mPackages) {
1399 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1400 while (i.hasNext()) {
1401 final PackageParser.Package p = i.next();
1402 PackageInfo pi = generatePackageInfo(p, flags);
1403 if (pi != null) {
1404 finalList.add(pi);
1405 }
1406 }
1407 }
1408
1409 return finalList;
1410 }
1411
1412 public List<ApplicationInfo> getInstalledApplications(int flags) {
1413 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1414
1415 synchronized (mPackages) {
1416 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1417 while (i.hasNext()) {
1418 final PackageParser.Package p = i.next();
1419 if (p.applicationInfo != null) {
1420 finalList.add(p.applicationInfo);
1421 }
1422 }
1423 }
1424
1425 return finalList;
1426 }
1427
1428 public List<ApplicationInfo> getPersistentApplications(int flags) {
1429 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1430
1431 synchronized (mPackages) {
1432 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1433 while (i.hasNext()) {
1434 PackageParser.Package p = i.next();
1435 if (p.applicationInfo != null
1436 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1437 && (!mSafeMode || (p.applicationInfo.flags
1438 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1439 finalList.add(p.applicationInfo);
1440 }
1441 }
1442 }
1443
1444 return finalList;
1445 }
1446
1447 public ProviderInfo resolveContentProvider(String name, int flags) {
1448 synchronized (mPackages) {
1449 final PackageParser.Provider provider = mProviders.get(name);
1450 return provider != null
1451 && mSettings.isEnabledLP(provider.info, flags)
1452 && (!mSafeMode || (provider.info.applicationInfo.flags
1453 &ApplicationInfo.FLAG_SYSTEM) != 0)
1454 ? PackageParser.generateProviderInfo(provider, flags)
1455 : null;
1456 }
1457 }
1458
1459 public void querySyncProviders(List outNames, List outInfo) {
1460 synchronized (mPackages) {
1461 Iterator<Map.Entry<String, PackageParser.Provider>> i
1462 = mProviders.entrySet().iterator();
1463
1464 while (i.hasNext()) {
1465 Map.Entry<String, PackageParser.Provider> entry = i.next();
1466 PackageParser.Provider p = entry.getValue();
1467
1468 if (p.syncable
1469 && (!mSafeMode || (p.info.applicationInfo.flags
1470 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1471 outNames.add(entry.getKey());
1472 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1473 }
1474 }
1475 }
1476 }
1477
1478 public List<ProviderInfo> queryContentProviders(String processName,
1479 int uid, int flags) {
1480 ArrayList<ProviderInfo> finalList = null;
1481
1482 synchronized (mPackages) {
1483 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1484 while (i.hasNext()) {
1485 PackageParser.Provider p = i.next();
1486 if (p.info.authority != null
1487 && (processName == null ||
1488 (p.info.processName.equals(processName)
1489 && p.info.applicationInfo.uid == uid))
1490 && mSettings.isEnabledLP(p.info, flags)
1491 && (!mSafeMode || (p.info.applicationInfo.flags
1492 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1493 if (finalList == null) {
1494 finalList = new ArrayList<ProviderInfo>(3);
1495 }
1496 finalList.add(PackageParser.generateProviderInfo(p,
1497 flags));
1498 }
1499 }
1500 }
1501
1502 if (finalList != null) {
1503 Collections.sort(finalList, mProviderInitOrderSorter);
1504 }
1505
1506 return finalList;
1507 }
1508
1509 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1510 int flags) {
1511 synchronized (mPackages) {
1512 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1513 return PackageParser.generateInstrumentationInfo(i, flags);
1514 }
1515 }
1516
1517 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1518 int flags) {
1519 ArrayList<InstrumentationInfo> finalList =
1520 new ArrayList<InstrumentationInfo>();
1521
1522 synchronized (mPackages) {
1523 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1524 while (i.hasNext()) {
1525 PackageParser.Instrumentation p = i.next();
1526 if (targetPackage == null
1527 || targetPackage.equals(p.info.targetPackage)) {
1528 finalList.add(PackageParser.generateInstrumentationInfo(p,
1529 flags));
1530 }
1531 }
1532 }
1533
1534 return finalList;
1535 }
1536
1537 private void scanDirLI(File dir, int flags, int scanMode) {
1538 Log.d(TAG, "Scanning app dir " + dir);
1539
1540 String[] files = dir.list();
1541
1542 int i;
1543 for (i=0; i<files.length; i++) {
1544 File file = new File(dir, files[i]);
1545 PackageParser.Package pkg = scanPackageLI(file, file, file,
1546 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1547 }
1548 }
1549
1550 private static void reportSettingsProblem(int priority, String msg) {
1551 try {
1552 File dataDir = Environment.getDataDirectory();
1553 File systemDir = new File(dataDir, "system");
1554 File fname = new File(systemDir, "uiderrors.txt");
1555 FileOutputStream out = new FileOutputStream(fname, true);
1556 PrintWriter pw = new PrintWriter(out);
1557 pw.println(msg);
1558 pw.close();
1559 FileUtils.setPermissions(
1560 fname.toString(),
1561 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1562 -1, -1);
1563 } catch (java.io.IOException e) {
1564 }
1565 Log.println(priority, TAG, msg);
1566 }
1567
1568 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1569 PackageParser.Package pkg, File srcFile, int parseFlags) {
1570 if (GET_CERTIFICATES) {
1571 if (ps == null || !ps.codePath.equals(srcFile)
1572 || ps.timeStamp != srcFile.lastModified()) {
1573 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1574 if (!pp.collectCertificates(pkg, parseFlags)) {
1575 mLastScanError = pp.getParseError();
1576 return false;
1577 }
1578 }
1579 }
1580 return true;
1581 }
1582
1583 private PackageParser.Package scanPackageLI(File scanFile,
1584 File destCodeFile, File destResourceFile, int parseFlags,
1585 int scanMode) {
1586 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1587 parseFlags |= mDefParseFlags;
1588 PackageParser pp = new PackageParser(scanFile.getPath());
1589 pp.setSeparateProcesses(mSeparateProcesses);
1590 pp.setSdkVersion(mSdkVersion);
1591 final PackageParser.Package pkg = pp.parsePackage(scanFile,
1592 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
1593 if (pkg == null) {
1594 mLastScanError = pp.getParseError();
1595 return null;
1596 }
1597 PackageSetting ps;
1598 synchronized (mPackages) {
1599 ps = mSettings.peekPackageLP(pkg.packageName,
1600 scanFile.toString());
1601 }
1602 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
1603 return null;
1604 }
1605 // The apk is forward locked (not public) if its code and resources
1606 // are kept in different files.
1607 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
1608 scanMode |= SCAN_FORWARD_LOCKED;
1609 }
1610 return scanPackageLI(scanFile, destCodeFile, destResourceFile,
1611 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
1612 }
1613
1614 private static String fixProcessName(String defProcessName,
1615 String processName, int uid) {
1616 if (processName == null) {
1617 return defProcessName;
1618 }
1619 return processName;
1620 }
1621
1622 private boolean verifySignaturesLP(PackageSetting pkgSetting,
1623 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
1624 if (pkg.mSignatures != null) {
1625 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
1626 updateSignature)) {
1627 Log.e(TAG, "Package " + pkg.packageName
1628 + " signatures do not match the previously installed version; ignoring!");
1629 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
1630 return false;
1631 }
1632
1633 if (pkgSetting.sharedUser != null) {
1634 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1635 pkg.mSignatures, updateSignature)) {
1636 Log.e(TAG, "Package " + pkg.packageName
1637 + " has no signatures that match those in shared user "
1638 + pkgSetting.sharedUser.name + "; ignoring!");
1639 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
1640 return false;
1641 }
1642 }
1643 } else {
1644 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1645 }
1646 return true;
1647 }
1648
1649 private PackageParser.Package scanPackageLI(
1650 File scanFile, File destCodeFile, File destResourceFile,
1651 PackageParser.Package pkg, int parseFlags, int scanMode) {
1652
1653 mScanningPath = scanFile;
1654 if (pkg == null) {
1655 return null;
1656 }
1657
1658 final String pkgName = pkg.applicationInfo.packageName;
1659 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1660 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
1661 }
1662
1663 if (pkgName.equals("android")) {
1664 synchronized (mPackages) {
1665 if (mAndroidApplication != null) {
1666 Log.w(TAG, "*************************************************");
1667 Log.w(TAG, "Core android package being redefined. Skipping.");
1668 Log.w(TAG, " file=" + mScanningPath);
1669 Log.w(TAG, "*************************************************");
1670 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1671 return null;
1672 }
1673
1674 // Set up information for our fall-back user intent resolution
1675 // activity.
1676 mPlatformPackage = pkg;
1677 pkg.mVersionCode = mSdkVersion;
1678 mAndroidApplication = pkg.applicationInfo;
1679 mResolveActivity.applicationInfo = mAndroidApplication;
1680 mResolveActivity.name = ResolverActivity.class.getName();
1681 mResolveActivity.packageName = mAndroidApplication.packageName;
1682 mResolveActivity.processName = mAndroidApplication.processName;
1683 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1684 mResolveActivity.flags = 0;
1685 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
1686 mResolveActivity.exported = true;
1687 mResolveActivity.enabled = true;
1688 mResolveInfo.activityInfo = mResolveActivity;
1689 mResolveInfo.priority = 0;
1690 mResolveInfo.preferredOrder = 0;
1691 mResolveInfo.match = 0;
1692 mResolveComponentName = new ComponentName(
1693 mAndroidApplication.packageName, mResolveActivity.name);
1694 }
1695 }
1696
1697 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
1698 TAG, "Scanning package " + pkgName);
1699 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
1700 Log.w(TAG, "*************************************************");
1701 Log.w(TAG, "Application package " + pkgName
1702 + " already installed. Skipping duplicate.");
1703 Log.w(TAG, "*************************************************");
1704 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
1705 return null;
1706 }
1707
1708 SharedUserSetting suid = null;
1709 PackageSetting pkgSetting = null;
1710
1711 boolean removeExisting = false;
1712
1713 synchronized (mPackages) {
1714 // Check all shared libraries and map to their actual file path.
1715 if (pkg.usesLibraryFiles != null) {
1716 for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
1717 String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
1718 if (file == null) {
1719 Log.e(TAG, "Package " + pkg.packageName
1720 + " requires unavailable shared library "
1721 + pkg.usesLibraryFiles[i] + "; ignoring!");
1722 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
1723 return null;
1724 }
1725 pkg.usesLibraryFiles[i] = file;
1726 }
1727 }
1728
1729 if (pkg.mSharedUserId != null) {
1730 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
1731 pkg.applicationInfo.flags, true);
1732 if (suid == null) {
1733 Log.w(TAG, "Creating application package " + pkgName
1734 + " for shared user failed");
1735 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1736 return null;
1737 }
1738 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
1739 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
1740 + suid.userId + "): packages=" + suid.packages);
1741 }
1742 }
1743
1744 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
1745 destResourceFile, pkg.applicationInfo.flags, true);
1746 if (pkgSetting == null) {
1747 Log.w(TAG, "Creating application package " + pkgName + " failed");
1748 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1749 return null;
1750 }
1751
1752 pkg.applicationInfo.uid = pkgSetting.userId;
1753 pkg.mExtras = pkgSetting;
1754
1755 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
1756 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
1757 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
1758 return null;
1759 }
1760 // The signature has changed, but this package is in the system
1761 // image... let's recover!
1762 pkg.mSignatures = pkgSetting.signatures.mSignatures;
1763 // However... if this package is part of a shared user, but it
1764 // doesn't match the signature of the shared user, let's fail.
1765 // What this means is that you can't change the signatures
1766 // associated with an overall shared user, which doesn't seem all
1767 // that unreasonable.
1768 if (pkgSetting.sharedUser != null) {
1769 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
1770 pkg.mSignatures, false)) {
1771 return null;
1772 }
1773 }
1774 removeExisting = true;
1775 }
1776 }
1777
1778 if (removeExisting) {
1779 if (mInstaller != null) {
1780 int ret = mInstaller.remove(pkgName);
1781 if (ret != 0) {
1782 String msg = "System package " + pkg.packageName
1783 + " could not have data directory erased after signature change.";
1784 reportSettingsProblem(Log.WARN, msg);
1785 return null;
1786 }
1787 }
1788 Log.w(TAG, "System package " + pkg.packageName
1789 + " signature changed: existing data removed.");
1790 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
1791 }
1792
1793 long scanFileTime = scanFile.lastModified();
1794 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
1795 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.timeStamp;
1796
1797 // At this point we know it is okay to accept the package, though
1798 // errors can still happen as we try to install...
1799
1800 if ((scanMode&SCAN_MONITOR) != 0) {
1801 pkg.mPath = destCodeFile.getAbsolutePath();
1802 mAppDirs.put(pkg.mPath, pkg);
1803 }
1804 pkg.applicationInfo.processName = fixProcessName(
1805 pkg.applicationInfo.packageName,
1806 pkg.applicationInfo.processName,
1807 pkg.applicationInfo.uid);
1808 pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
1809
1810 synchronized (mPackages) {
1811 mPackages.put(pkg.applicationInfo.packageName, pkg);
1812 }
1813
1814 File dataPath;
1815 if (mPlatformPackage == pkg) {
1816 // The system package is special.
1817 dataPath = new File (Environment.getDataDirectory(), "system");
1818 pkg.applicationInfo.dataDir = dataPath.getPath();
1819 } else {
1820 // This is a normal package, need to make its data directory.
1821 dataPath = new File(mAppDataDir, pkgName);
1822 if (dataPath.exists()) {
1823 mOutPermissions[1] = 0;
1824 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
1825 if (mOutPermissions[1] == pkg.applicationInfo.uid
1826 || !Process.supportsProcesses()) {
1827 pkg.applicationInfo.dataDir = dataPath.getPath();
1828 } else {
1829 boolean recovered = false;
1830 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
1831 // If this is a system app, we can at least delete its
1832 // current data so the application will still work.
1833 if (mInstaller != null) {
1834 int ret = mInstaller.remove(pkgName);
1835 if(ret >= 0) {
1836 // Old data gone!
1837 String msg = "System package " + pkg.packageName
1838 + " has changed from uid: "
1839 + mOutPermissions[1] + " to "
1840 + pkg.applicationInfo.uid + "; old data erased";
1841 reportSettingsProblem(Log.WARN, msg);
1842 recovered = true;
1843
1844 // And now re-install the app.
1845 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
1846 pkg.applicationInfo.uid);
1847 if (ret == -1) {
1848 // Ack should not happen!
1849 msg = "System package " + pkg.packageName
1850 + " could not have data directory re-created after delete.";
1851 reportSettingsProblem(Log.WARN, msg);
1852 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1853 return null;
1854 }
1855 }
1856
1857 }
1858 if (!recovered) {
1859 mHasSystemUidErrors = true;
1860 }
1861 }
1862 if (!recovered) {
1863 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
1864 + pkg.applicationInfo.uid + "/fs_"
1865 + mOutPermissions[1];
1866 String msg = "Package " + pkg.packageName
1867 + " has mismatched uid: "
1868 + mOutPermissions[1] + " on disk, "
1869 + pkg.applicationInfo.uid + " in settings";
1870 synchronized (mPackages) {
1871 if (!mReportedUidError) {
1872 mReportedUidError = true;
1873 msg = msg + "; read messages:\n"
1874 + mSettings.getReadMessagesLP();
1875 }
1876 reportSettingsProblem(Log.ERROR, msg);
1877 }
1878 }
1879 }
1880 pkg.applicationInfo.dataDir = dataPath.getPath();
1881 } else {
1882 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
1883 Log.v(TAG, "Want this data dir: " + dataPath);
1884 //invoke installer to do the actual installation
1885 if (mInstaller != null) {
1886 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
1887 pkg.applicationInfo.uid);
1888 if(ret < 0) {
1889 //error from installer
1890 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1891 return null;
1892 }
1893 } else {
1894 dataPath.mkdirs();
1895 if (dataPath.exists()) {
1896 FileUtils.setPermissions(
1897 dataPath.toString(),
1898 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1899 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
1900 }
1901 }
1902 if (dataPath.exists()) {
1903 pkg.applicationInfo.dataDir = dataPath.getPath();
1904 } else {
1905 Log.w(TAG, "Unable to create data directory: " + dataPath);
1906 pkg.applicationInfo.dataDir = null;
1907 }
1908 }
1909 }
1910
1911 // Perform shared library installation and dex validation and
1912 // optimization, if this is not a system app.
1913 if (mInstaller != null) {
1914 String path = scanFile.getPath();
1915 if (scanFileNewer) {
1916 Log.i(TAG, path + " changed; unpacking");
1917 try {
1918 cachePackageSharedLibsLI(pkg, dataPath, scanFile);
1919 } catch (IOException e) {
1920 Log.e(TAG, "Failure extracting shared libs", e);
1921 if(mInstaller != null) {
1922 mInstaller.remove(pkgName);
1923 } else {
1924 dataPath.delete();
1925 }
1926 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
1927 return null;
1928 }
1929 }
1930
1931 if ((scanMode&SCAN_NO_DEX) == 0
1932 && (pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
1933 int ret = 0;
1934 try {
1935 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
1936 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
1937 (scanMode&SCAN_FORWARD_LOCKED) == 0);
1938 }
1939 } catch (FileNotFoundException e) {
1940 Log.w(TAG, "Apk not found for dexopt: " + path);
1941 ret = -1;
1942 } catch (IOException e) {
1943 Log.w(TAG, "Exception reading apk: " + path, e);
1944 ret = -1;
1945 }
1946 if (ret < 0) {
1947 //error from installer
1948 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
1949 return null;
1950 }
1951 }
1952 }
1953
1954 if (mFactoryTest && pkg.requestedPermissions.contains(
1955 android.Manifest.permission.FACTORY_TEST)) {
1956 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
1957 }
1958
1959 synchronized (mPackages) {
1960
1961 int N = pkg.providers.size();
1962 StringBuilder r = null;
1963 int i;
1964 for (i=0; i<N; i++) {
1965 PackageParser.Provider p = pkg.providers.get(i);
1966 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
1967 p.info.processName, pkg.applicationInfo.uid);
1968 mProvidersByComponent.put(new ComponentName(p.info.packageName,
1969 p.info.name), p);
1970 p.syncable = p.info.isSyncable;
1971 String names[] = p.info.authority.split(";");
1972 p.info.authority = null;
1973 for (int j = 0; j < names.length; j++) {
1974 if (j == 1 && p.syncable) {
1975 // We only want the first authority for a provider to possibly be
1976 // syncable, so if we already added this provider using a different
1977 // authority clear the syncable flag. We copy the provider before
1978 // changing it because the mProviders object contains a reference
1979 // to a provider that we don't want to change.
1980 // Only do this for the second authority since the resulting provider
1981 // object can be the same for all future authorities for this provider.
1982 p = new PackageParser.Provider(p);
1983 p.syncable = false;
1984 }
1985 if (!mProviders.containsKey(names[j])) {
1986 mProviders.put(names[j], p);
1987 if (p.info.authority == null) {
1988 p.info.authority = names[j];
1989 } else {
1990 p.info.authority = p.info.authority + ";" + names[j];
1991 }
1992 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
1993 Log.d(TAG, "Registered content provider: " + names[j] +
1994 ", className = " + p.info.name +
1995 ", isSyncable = " + p.info.isSyncable);
1996 } else {
1997 Log.w(TAG, "Skipping provider name " + names[j] +
1998 " (in package " + pkg.applicationInfo.packageName +
1999 "): name already used");
2000 }
2001 }
2002 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2003 if (r == null) {
2004 r = new StringBuilder(256);
2005 } else {
2006 r.append(' ');
2007 }
2008 r.append(p.info.name);
2009 }
2010 }
2011 if (r != null) {
2012 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2013 }
2014
2015 N = pkg.services.size();
2016 r = null;
2017 for (i=0; i<N; i++) {
2018 PackageParser.Service s = pkg.services.get(i);
2019 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2020 s.info.processName, pkg.applicationInfo.uid);
2021 mServices.addService(s);
2022 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2023 if (r == null) {
2024 r = new StringBuilder(256);
2025 } else {
2026 r.append(' ');
2027 }
2028 r.append(s.info.name);
2029 }
2030 }
2031 if (r != null) {
2032 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2033 }
2034
2035 N = pkg.receivers.size();
2036 r = null;
2037 for (i=0; i<N; i++) {
2038 PackageParser.Activity a = pkg.receivers.get(i);
2039 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2040 a.info.processName, pkg.applicationInfo.uid);
2041 mReceivers.addActivity(a, "receiver");
2042 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2043 if (r == null) {
2044 r = new StringBuilder(256);
2045 } else {
2046 r.append(' ');
2047 }
2048 r.append(a.info.name);
2049 }
2050 }
2051 if (r != null) {
2052 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2053 }
2054
2055 N = pkg.activities.size();
2056 r = null;
2057 for (i=0; i<N; i++) {
2058 PackageParser.Activity a = pkg.activities.get(i);
2059 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2060 a.info.processName, pkg.applicationInfo.uid);
2061 mActivities.addActivity(a, "activity");
2062 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2063 if (r == null) {
2064 r = new StringBuilder(256);
2065 } else {
2066 r.append(' ');
2067 }
2068 r.append(a.info.name);
2069 }
2070 }
2071 if (r != null) {
2072 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2073 }
2074
2075 N = pkg.permissionGroups.size();
2076 r = null;
2077 for (i=0; i<N; i++) {
2078 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2079 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2080 if (cur == null) {
2081 mPermissionGroups.put(pg.info.name, pg);
2082 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2083 if (r == null) {
2084 r = new StringBuilder(256);
2085 } else {
2086 r.append(' ');
2087 }
2088 r.append(pg.info.name);
2089 }
2090 } else {
2091 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2092 + pg.info.packageName + " ignored: original from "
2093 + cur.info.packageName);
2094 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2095 if (r == null) {
2096 r = new StringBuilder(256);
2097 } else {
2098 r.append(' ');
2099 }
2100 r.append("DUP:");
2101 r.append(pg.info.name);
2102 }
2103 }
2104 }
2105 if (r != null) {
2106 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2107 }
2108
2109 N = pkg.permissions.size();
2110 r = null;
2111 for (i=0; i<N; i++) {
2112 PackageParser.Permission p = pkg.permissions.get(i);
2113 HashMap<String, BasePermission> permissionMap =
2114 p.tree ? mSettings.mPermissionTrees
2115 : mSettings.mPermissions;
2116 p.group = mPermissionGroups.get(p.info.group);
2117 if (p.info.group == null || p.group != null) {
2118 BasePermission bp = permissionMap.get(p.info.name);
2119 if (bp == null) {
2120 bp = new BasePermission(p.info.name, p.info.packageName,
2121 BasePermission.TYPE_NORMAL);
2122 permissionMap.put(p.info.name, bp);
2123 }
2124 if (bp.perm == null) {
2125 if (bp.sourcePackage == null
2126 || bp.sourcePackage.equals(p.info.packageName)) {
2127 BasePermission tree = findPermissionTreeLP(p.info.name);
2128 if (tree == null
2129 || tree.sourcePackage.equals(p.info.packageName)) {
2130 bp.perm = p;
2131 bp.uid = pkg.applicationInfo.uid;
2132 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2133 if (r == null) {
2134 r = new StringBuilder(256);
2135 } else {
2136 r.append(' ');
2137 }
2138 r.append(p.info.name);
2139 }
2140 } else {
2141 Log.w(TAG, "Permission " + p.info.name + " from package "
2142 + p.info.packageName + " ignored: base tree "
2143 + tree.name + " is from package "
2144 + tree.sourcePackage);
2145 }
2146 } else {
2147 Log.w(TAG, "Permission " + p.info.name + " from package "
2148 + p.info.packageName + " ignored: original from "
2149 + bp.sourcePackage);
2150 }
2151 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2152 if (r == null) {
2153 r = new StringBuilder(256);
2154 } else {
2155 r.append(' ');
2156 }
2157 r.append("DUP:");
2158 r.append(p.info.name);
2159 }
2160 } else {
2161 Log.w(TAG, "Permission " + p.info.name + " from package "
2162 + p.info.packageName + " ignored: no group "
2163 + p.group);
2164 }
2165 }
2166 if (r != null) {
2167 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2168 }
2169
2170 N = pkg.instrumentation.size();
2171 r = null;
2172 for (i=0; i<N; i++) {
2173 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2174 a.info.packageName = pkg.applicationInfo.packageName;
2175 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2176 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2177 a.info.dataDir = pkg.applicationInfo.dataDir;
2178 mInstrumentation.put(a.component, a);
2179 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2180 if (r == null) {
2181 r = new StringBuilder(256);
2182 } else {
2183 r.append(' ');
2184 }
2185 r.append(a.info.name);
2186 }
2187 }
2188 if (r != null) {
2189 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2190 }
2191
2192 pkgSetting.setTimeStamp(scanFileTime);
2193 }
2194
2195 return pkg;
2196 }
2197
2198 private void cachePackageSharedLibsLI(PackageParser.Package pkg,
2199 File dataPath, File scanFile) throws IOException {
2200 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2201 final String sharedLibraryABI = "armeabi";
2202 final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
2203 final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
2204 final String sharedLibrarySuffix = ".so";
2205 boolean createdSharedLib = false;
2206 try {
2207 ZipFile zipFile = new ZipFile(scanFile);
2208 Enumeration<ZipEntry> entries =
2209 (Enumeration<ZipEntry>) zipFile.entries();
2210
2211 while (entries.hasMoreElements()) {
2212 ZipEntry entry = entries.nextElement();
2213 if (entry.isDirectory()) {
2214 continue;
2215 }
2216 String entryName = entry.getName();
2217 if (! (entryName.startsWith(apkSharedLibraryPrefix)
2218 && entryName.endsWith(sharedLibrarySuffix))) {
2219 continue;
2220 }
2221 String libFileName = entryName.substring(
2222 apkLibraryDirectory.length());
2223 if (libFileName.contains("/")
2224 || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
2225 continue;
2226 }
2227 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2228 File.separator + libFileName;
2229 File sharedLibraryFile = new File(sharedLibraryFilePath);
2230 if (! sharedLibraryFile.exists() ||
2231 sharedLibraryFile.length() != entry.getSize() ||
2232 sharedLibraryFile.lastModified() != entry.getTime()) {
2233 if (Config.LOGD) {
2234 Log.d(TAG, "Caching shared lib " + entry.getName());
2235 }
2236 if (mInstaller == null) {
2237 sharedLibraryDir.mkdir();
2238 createdSharedLib = true;
2239 }
2240 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2241 sharedLibraryFile);
2242 }
2243 }
2244 } catch (IOException e) {
2245 Log.e(TAG, "Failed to cache package shared libs", e);
2246 if(createdSharedLib) {
2247 sharedLibraryDir.delete();
2248 }
2249 throw e;
2250 }
2251 }
2252
2253 private void cacheSharedLibLI(PackageParser.Package pkg,
2254 ZipFile zipFile, ZipEntry entry,
2255 File sharedLibraryDir,
2256 File sharedLibraryFile) throws IOException {
2257 InputStream inputStream = zipFile.getInputStream(entry);
2258 try {
2259 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2260 String tempFilePath = tempFile.getPath();
2261 // XXX package manager can't change owner, so the lib files for
2262 // now need to be left as world readable and owned by the system.
2263 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2264 ! tempFile.setLastModified(entry.getTime()) ||
2265 FileUtils.setPermissions(tempFilePath,
2266 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2267 |FileUtils.S_IROTH, -1, -1) != 0 ||
2268 ! tempFile.renameTo(sharedLibraryFile)) {
2269 // Failed to properly write file.
2270 tempFile.delete();
2271 throw new IOException("Couldn't create cached shared lib "
2272 + sharedLibraryFile + " in " + sharedLibraryDir);
2273 }
2274 } finally {
2275 inputStream.close();
2276 }
2277 }
2278
2279 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2280 if (chatty && Config.LOGD) Log.d(
2281 TAG, "Removing package " + pkg.applicationInfo.packageName );
2282
2283 synchronized (mPackages) {
2284 if (pkg.mPreferredOrder > 0) {
2285 mSettings.mPreferredPackages.remove(pkg);
2286 pkg.mPreferredOrder = 0;
2287 updatePreferredIndicesLP();
2288 }
2289
2290 clearPackagePreferredActivitiesLP(pkg.packageName);
2291
2292 mPackages.remove(pkg.applicationInfo.packageName);
2293 if (pkg.mPath != null) {
2294 mAppDirs.remove(pkg.mPath);
2295 }
2296
2297 PackageSetting ps = (PackageSetting)pkg.mExtras;
2298 if (ps != null && ps.sharedUser != null) {
2299 // XXX don't do this until the data is removed.
2300 if (false) {
2301 ps.sharedUser.packages.remove(ps);
2302 if (ps.sharedUser.packages.size() == 0) {
2303 // Remove.
2304 }
2305 }
2306 }
2307
2308 int N = pkg.providers.size();
2309 StringBuilder r = null;
2310 int i;
2311 for (i=0; i<N; i++) {
2312 PackageParser.Provider p = pkg.providers.get(i);
2313 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2314 p.info.name));
2315 if (p.info.authority == null) {
2316
2317 /* The is another ContentProvider with this authority when
2318 * this app was installed so this authority is null,
2319 * Ignore it as we don't have to unregister the provider.
2320 */
2321 continue;
2322 }
2323 String names[] = p.info.authority.split(";");
2324 for (int j = 0; j < names.length; j++) {
2325 if (mProviders.get(names[j]) == p) {
2326 mProviders.remove(names[j]);
2327 if (chatty && Config.LOGD) Log.d(
2328 TAG, "Unregistered content provider: " + names[j] +
2329 ", className = " + p.info.name +
2330 ", isSyncable = " + p.info.isSyncable);
2331 }
2332 }
2333 if (chatty) {
2334 if (r == null) {
2335 r = new StringBuilder(256);
2336 } else {
2337 r.append(' ');
2338 }
2339 r.append(p.info.name);
2340 }
2341 }
2342 if (r != null) {
2343 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2344 }
2345
2346 N = pkg.services.size();
2347 r = null;
2348 for (i=0; i<N; i++) {
2349 PackageParser.Service s = pkg.services.get(i);
2350 mServices.removeService(s);
2351 if (chatty) {
2352 if (r == null) {
2353 r = new StringBuilder(256);
2354 } else {
2355 r.append(' ');
2356 }
2357 r.append(s.info.name);
2358 }
2359 }
2360 if (r != null) {
2361 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2362 }
2363
2364 N = pkg.receivers.size();
2365 r = null;
2366 for (i=0; i<N; i++) {
2367 PackageParser.Activity a = pkg.receivers.get(i);
2368 mReceivers.removeActivity(a, "receiver");
2369 if (chatty) {
2370 if (r == null) {
2371 r = new StringBuilder(256);
2372 } else {
2373 r.append(' ');
2374 }
2375 r.append(a.info.name);
2376 }
2377 }
2378 if (r != null) {
2379 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2380 }
2381
2382 N = pkg.activities.size();
2383 r = null;
2384 for (i=0; i<N; i++) {
2385 PackageParser.Activity a = pkg.activities.get(i);
2386 mActivities.removeActivity(a, "activity");
2387 if (chatty) {
2388 if (r == null) {
2389 r = new StringBuilder(256);
2390 } else {
2391 r.append(' ');
2392 }
2393 r.append(a.info.name);
2394 }
2395 }
2396 if (r != null) {
2397 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2398 }
2399
2400 N = pkg.permissions.size();
2401 r = null;
2402 for (i=0; i<N; i++) {
2403 PackageParser.Permission p = pkg.permissions.get(i);
2404 boolean tree = false;
2405 BasePermission bp = mSettings.mPermissions.get(p.info.name);
2406 if (bp == null) {
2407 tree = true;
2408 bp = mSettings.mPermissionTrees.get(p.info.name);
2409 }
2410 if (bp != null && bp.perm == p) {
2411 if (bp.type != BasePermission.TYPE_BUILTIN) {
2412 if (tree) {
2413 mSettings.mPermissionTrees.remove(p.info.name);
2414 } else {
2415 mSettings.mPermissions.remove(p.info.name);
2416 }
2417 } else {
2418 bp.perm = null;
2419 }
2420 if (chatty) {
2421 if (r == null) {
2422 r = new StringBuilder(256);
2423 } else {
2424 r.append(' ');
2425 }
2426 r.append(p.info.name);
2427 }
2428 }
2429 }
2430 if (r != null) {
2431 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2432 }
2433
2434 N = pkg.instrumentation.size();
2435 r = null;
2436 for (i=0; i<N; i++) {
2437 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2438 mInstrumentation.remove(a.component);
2439 if (chatty) {
2440 if (r == null) {
2441 r = new StringBuilder(256);
2442 } else {
2443 r.append(' ');
2444 }
2445 r.append(a.info.name);
2446 }
2447 }
2448 if (r != null) {
2449 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2450 }
2451 }
2452 }
2453
2454 private static final boolean isPackageFilename(String name) {
2455 return name != null && name.endsWith(".apk");
2456 }
2457
2458 private void updatePermissionsLP() {
2459 // Make sure there are no dangling permission trees.
2460 Iterator<BasePermission> it = mSettings.mPermissionTrees
2461 .values().iterator();
2462 while (it.hasNext()) {
2463 BasePermission bp = it.next();
2464 if (bp.perm == null) {
2465 Log.w(TAG, "Removing dangling permission tree: " + bp.name
2466 + " from package " + bp.sourcePackage);
2467 it.remove();
2468 }
2469 }
2470
2471 // Make sure all dynamic permissions have been assigned to a package,
2472 // and make sure there are no dangling permissions.
2473 it = mSettings.mPermissions.values().iterator();
2474 while (it.hasNext()) {
2475 BasePermission bp = it.next();
2476 if (bp.type == BasePermission.TYPE_DYNAMIC) {
2477 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
2478 + bp.name + " pkg=" + bp.sourcePackage
2479 + " info=" + bp.pendingInfo);
2480 if (bp.perm == null && bp.pendingInfo != null) {
2481 BasePermission tree = findPermissionTreeLP(bp.name);
2482 if (tree != null) {
2483 bp.perm = new PackageParser.Permission(tree.perm.owner,
2484 new PermissionInfo(bp.pendingInfo));
2485 bp.perm.info.packageName = tree.perm.info.packageName;
2486 bp.perm.info.name = bp.name;
2487 bp.uid = tree.uid;
2488 }
2489 }
2490 }
2491 if (bp.perm == null) {
2492 Log.w(TAG, "Removing dangling permission: " + bp.name
2493 + " from package " + bp.sourcePackage);
2494 it.remove();
2495 }
2496 }
2497
2498 // Now update the permissions for all packages, in particular
2499 // replace the granted permissions of the system packages.
2500 for (PackageParser.Package pkg : mPackages.values()) {
2501 grantPermissionsLP(pkg, false);
2502 }
2503 }
2504
2505 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
2506 final PackageSetting ps = (PackageSetting)pkg.mExtras;
2507 if (ps == null) {
2508 return;
2509 }
2510 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2511 boolean addedPermission = false;
2512
2513 if (replace) {
2514 ps.permissionsFixed = false;
2515 if (gp == ps) {
2516 gp.grantedPermissions.clear();
2517 gp.gids = mGlobalGids;
2518 }
2519 }
2520
2521 if (gp.gids == null) {
2522 gp.gids = mGlobalGids;
2523 }
2524
2525 final int N = pkg.requestedPermissions.size();
2526 for (int i=0; i<N; i++) {
2527 String name = pkg.requestedPermissions.get(i);
2528 BasePermission bp = mSettings.mPermissions.get(name);
2529 PackageParser.Permission p = bp != null ? bp.perm : null;
2530 if (false) {
2531 if (gp != ps) {
2532 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
2533 + ": " + p);
2534 }
2535 }
2536 if (p != null) {
2537 final String perm = p.info.name;
2538 boolean allowed;
2539 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
2540 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
2541 allowed = true;
2542 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
2543 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2544 allowed = (checkSignaturesLP(p.owner, pkg)
2545 == PackageManager.SIGNATURE_MATCH)
2546 || (checkSignaturesLP(mPlatformPackage, pkg)
2547 == PackageManager.SIGNATURE_MATCH);
2548 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
2549 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
2550 allowed = true;
2551 }
2552 }
2553 } else {
2554 allowed = false;
2555 }
2556 if (false) {
2557 if (gp != ps) {
2558 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
2559 }
2560 }
2561 if (allowed) {
2562 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
2563 && ps.permissionsFixed) {
2564 // If this is an existing, non-system package, then
2565 // we can't add any new permissions to it.
2566 if (!gp.loadedPermissions.contains(perm)) {
2567 allowed = false;
2568 }
2569 }
2570 if (allowed) {
2571 if (!gp.grantedPermissions.contains(perm)) {
2572 addedPermission = true;
2573 gp.grantedPermissions.add(perm);
2574 gp.gids = appendInts(gp.gids, bp.gids);
2575 }
2576 } else {
2577 Log.w(TAG, "Not granting permission " + perm
2578 + " to package " + pkg.packageName
2579 + " because it was previously installed without");
2580 }
2581 } else {
2582 Log.w(TAG, "Not granting permission " + perm
2583 + " to package " + pkg.packageName
2584 + " (protectionLevel=" + p.info.protectionLevel
2585 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
2586 + ")");
2587 }
2588 } else {
2589 Log.w(TAG, "Unknown permission " + name
2590 + " in package " + pkg.packageName);
2591 }
2592 }
2593
2594 if ((addedPermission || replace) && !ps.permissionsFixed &&
2595 (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2596 // This is the first that we have heard about this package, so the
2597 // permissions we have now selected are fixed until explicitly
2598 // changed.
2599 ps.permissionsFixed = true;
2600 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
2601 }
2602 }
2603
2604 private final class ActivityIntentResolver
2605 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
2606 public List queryIntent(ContentResolver resolver, Intent intent,
2607 String resolvedType, boolean defaultOnly) {
2608 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2609 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2610 }
2611
2612 public List queryIntent(ContentResolver resolver, Intent intent,
2613 String resolvedType, int flags) {
2614 mFlags = flags;
2615 return super.queryIntent(
2616 resolver, intent, resolvedType,
2617 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2618 }
2619
2620 public final void addActivity(PackageParser.Activity a, String type) {
2621 mActivities.put(a.component, a);
2622 if (SHOW_INFO || Config.LOGV) Log.v(
2623 TAG, " " + type + " " +
2624 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2625 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2626 int NI = a.intents.size();
2627 int j;
2628 for (j=0; j<NI; j++) {
2629 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2630 if (SHOW_INFO || Config.LOGV) {
2631 Log.v(TAG, " IntentFilter:");
2632 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2633 }
2634 if (!intent.debugCheck()) {
2635 Log.w(TAG, "==> For Activity " + a.info.name);
2636 }
2637 addFilter(intent);
2638 }
2639 }
2640
2641 public final void removeActivity(PackageParser.Activity a, String type) {
2642 mActivities.remove(a.component);
2643 if (SHOW_INFO || Config.LOGV) Log.v(
2644 TAG, " " + type + " " +
2645 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
2646 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
2647 int NI = a.intents.size();
2648 int j;
2649 for (j=0; j<NI; j++) {
2650 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
2651 if (SHOW_INFO || Config.LOGV) {
2652 Log.v(TAG, " IntentFilter:");
2653 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2654 }
2655 removeFilter(intent);
2656 }
2657 }
2658
2659 @Override
2660 protected boolean allowFilterResult(
2661 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
2662 ActivityInfo filterAi = filter.activity.info;
2663 for (int i=dest.size()-1; i>=0; i--) {
2664 ActivityInfo destAi = dest.get(i).activityInfo;
2665 if (destAi.name == filterAi.name
2666 && destAi.packageName == filterAi.packageName) {
2667 return false;
2668 }
2669 }
2670 return true;
2671 }
2672
2673 @Override
2674 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
2675 int match) {
2676 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
2677 return null;
2678 }
2679 final PackageParser.Activity activity = info.activity;
2680 if (mSafeMode && (activity.info.applicationInfo.flags
2681 &ApplicationInfo.FLAG_SYSTEM) == 0) {
2682 return null;
2683 }
2684 final ResolveInfo res = new ResolveInfo();
2685 res.activityInfo = PackageParser.generateActivityInfo(activity,
2686 mFlags);
2687 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
2688 res.filter = info;
2689 }
2690 res.priority = info.getPriority();
2691 res.preferredOrder = activity.owner.mPreferredOrder;
2692 //System.out.println("Result: " + res.activityInfo.className +
2693 // " = " + res.priority);
2694 res.match = match;
2695 res.isDefault = info.hasDefault;
2696 res.labelRes = info.labelRes;
2697 res.nonLocalizedLabel = info.nonLocalizedLabel;
2698 res.icon = info.icon;
2699 return res;
2700 }
2701
2702 @Override
2703 protected void sortResults(List<ResolveInfo> results) {
2704 Collections.sort(results, mResolvePrioritySorter);
2705 }
2706
2707 @Override
2708 protected void dumpFilter(Printer out, String prefix,
2709 PackageParser.ActivityIntentInfo filter) {
2710 out.println(prefix
2711 + Integer.toHexString(System.identityHashCode(filter.activity))
2712 + " " + filter.activity.component.flattenToShortString());
2713 }
2714
2715// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
2716// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
2717// final List<ResolveInfo> retList = Lists.newArrayList();
2718// while (i.hasNext()) {
2719// final ResolveInfo resolveInfo = i.next();
2720// if (isEnabledLP(resolveInfo.activityInfo)) {
2721// retList.add(resolveInfo);
2722// }
2723// }
2724// return retList;
2725// }
2726
2727 // Keys are String (activity class name), values are Activity.
2728 private final HashMap<ComponentName, PackageParser.Activity> mActivities
2729 = new HashMap<ComponentName, PackageParser.Activity>();
2730 private int mFlags;
2731 }
2732
2733 private final class ServiceIntentResolver
2734 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
2735 public List queryIntent(ContentResolver resolver, Intent intent,
2736 String resolvedType, boolean defaultOnly) {
2737 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
2738 return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
2739 }
2740
2741 public List queryIntent(ContentResolver resolver, Intent intent,
2742 String resolvedType, int flags) {
2743 mFlags = flags;
2744 return super.queryIntent(
2745 resolver, intent, resolvedType,
2746 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2747 }
2748
2749 public final void addService(PackageParser.Service s) {
2750 mServices.put(s.component, s);
2751 if (SHOW_INFO || Config.LOGV) Log.v(
2752 TAG, " " + (s.info.nonLocalizedLabel != null
2753 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2754 if (SHOW_INFO || Config.LOGV) Log.v(
2755 TAG, " Class=" + s.info.name);
2756 int NI = s.intents.size();
2757 int j;
2758 for (j=0; j<NI; j++) {
2759 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
2760 if (SHOW_INFO || Config.LOGV) {
2761 Log.v(TAG, " IntentFilter:");
2762 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2763 }
2764 if (!intent.debugCheck()) {
2765 Log.w(TAG, "==> For Service " + s.info.name);
2766 }
2767 addFilter(intent);
2768 }
2769 }
2770
2771 public final void removeService(PackageParser.Service s) {
2772 mServices.remove(s.component);
2773 if (SHOW_INFO || Config.LOGV) Log.v(
2774 TAG, " " + (s.info.nonLocalizedLabel != null
2775 ? s.info.nonLocalizedLabel : s.info.name) + ":");
2776 if (SHOW_INFO || Config.LOGV) Log.v(
2777 TAG, " Class=" + s.info.name);
2778 int NI = s.intents.size();
2779 int j;
2780 for (j=0; j<NI; j++) {
2781 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
2782 if (SHOW_INFO || Config.LOGV) {
2783 Log.v(TAG, " IntentFilter:");
2784 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2785 }
2786 removeFilter(intent);
2787 }
2788 }
2789
2790 @Override
2791 protected boolean allowFilterResult(
2792 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
2793 ServiceInfo filterSi = filter.service.info;
2794 for (int i=dest.size()-1; i>=0; i--) {
2795 ServiceInfo destAi = dest.get(i).serviceInfo;
2796 if (destAi.name == filterSi.name
2797 && destAi.packageName == filterSi.packageName) {
2798 return false;
2799 }
2800 }
2801 return true;
2802 }
2803
2804 @Override
2805 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
2806 int match) {
2807 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
2808 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
2809 return null;
2810 }
2811 final PackageParser.Service service = info.service;
2812 if (mSafeMode && (service.info.applicationInfo.flags
2813 &ApplicationInfo.FLAG_SYSTEM) == 0) {
2814 return null;
2815 }
2816 final ResolveInfo res = new ResolveInfo();
2817 res.serviceInfo = PackageParser.generateServiceInfo(service,
2818 mFlags);
2819 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
2820 res.filter = filter;
2821 }
2822 res.priority = info.getPriority();
2823 res.preferredOrder = service.owner.mPreferredOrder;
2824 //System.out.println("Result: " + res.activityInfo.className +
2825 // " = " + res.priority);
2826 res.match = match;
2827 res.isDefault = info.hasDefault;
2828 res.labelRes = info.labelRes;
2829 res.nonLocalizedLabel = info.nonLocalizedLabel;
2830 res.icon = info.icon;
2831 return res;
2832 }
2833
2834 @Override
2835 protected void sortResults(List<ResolveInfo> results) {
2836 Collections.sort(results, mResolvePrioritySorter);
2837 }
2838
2839 @Override
2840 protected void dumpFilter(Printer out, String prefix,
2841 PackageParser.ServiceIntentInfo filter) {
2842 out.println(prefix
2843 + Integer.toHexString(System.identityHashCode(filter.service))
2844 + " " + filter.service.component.flattenToShortString());
2845 }
2846
2847// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
2848// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
2849// final List<ResolveInfo> retList = Lists.newArrayList();
2850// while (i.hasNext()) {
2851// final ResolveInfo resolveInfo = (ResolveInfo) i;
2852// if (isEnabledLP(resolveInfo.serviceInfo)) {
2853// retList.add(resolveInfo);
2854// }
2855// }
2856// return retList;
2857// }
2858
2859 // Keys are String (activity class name), values are Activity.
2860 private final HashMap<ComponentName, PackageParser.Service> mServices
2861 = new HashMap<ComponentName, PackageParser.Service>();
2862 private int mFlags;
2863 };
2864
2865 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
2866 new Comparator<ResolveInfo>() {
2867 public int compare(ResolveInfo r1, ResolveInfo r2) {
2868 int v1 = r1.priority;
2869 int v2 = r2.priority;
2870 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
2871 if (v1 != v2) {
2872 return (v1 > v2) ? -1 : 1;
2873 }
2874 v1 = r1.preferredOrder;
2875 v2 = r2.preferredOrder;
2876 if (v1 != v2) {
2877 return (v1 > v2) ? -1 : 1;
2878 }
2879 if (r1.isDefault != r2.isDefault) {
2880 return r1.isDefault ? -1 : 1;
2881 }
2882 v1 = r1.match;
2883 v2 = r2.match;
2884 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
2885 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
2886 }
2887 };
2888
2889 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
2890 new Comparator<ProviderInfo>() {
2891 public int compare(ProviderInfo p1, ProviderInfo p2) {
2892 final int v1 = p1.initOrder;
2893 final int v2 = p2.initOrder;
2894 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
2895 }
2896 };
2897
2898 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
2899 IActivityManager am = ActivityManagerNative.getDefault();
2900 if (am != null) {
2901 try {
2902 final Intent intent = new Intent(action,
2903 pkg != null ? Uri.fromParts("package", pkg, null) : null);
2904 if (extras != null) {
2905 intent.putExtras(extras);
2906 }
2907 am.broadcastIntent(
2908 null, intent,
2909 null, null, 0, null, null, null, false, false);
2910 } catch (RemoteException ex) {
2911 }
2912 }
2913 }
2914
2915 private final class AppDirObserver extends FileObserver {
2916 public AppDirObserver(String path, int mask, boolean isrom) {
2917 super(path, mask);
2918 mRootDir = path;
2919 mIsRom = isrom;
2920 }
2921
2922 public void onEvent(int event, String path) {
2923 String removedPackage = null;
2924 int removedUid = -1;
2925 String addedPackage = null;
2926 int addedUid = -1;
2927
2928 synchronized (mInstallLock) {
2929 String fullPathStr = null;
2930 File fullPath = null;
2931 if (path != null) {
2932 fullPath = new File(mRootDir, path);
2933 fullPathStr = fullPath.getPath();
2934 }
2935
2936 if (Config.LOGV) Log.v(
2937 TAG, "File " + fullPathStr + " changed: "
2938 + Integer.toHexString(event));
2939
2940 if (!isPackageFilename(path)) {
2941 if (Config.LOGV) Log.v(
2942 TAG, "Ignoring change of non-package file: " + fullPathStr);
2943 return;
2944 }
2945
2946 if ((event&REMOVE_EVENTS) != 0) {
2947 synchronized (mInstallLock) {
2948 PackageParser.Package p = mAppDirs.get(fullPathStr);
2949 if (p != null) {
2950 removePackageLI(p, true);
2951 removedPackage = p.applicationInfo.packageName;
2952 removedUid = p.applicationInfo.uid;
2953 }
2954 }
2955 }
2956
2957 if ((event&ADD_EVENTS) != 0) {
2958 PackageParser.Package p = mAppDirs.get(fullPathStr);
2959 if (p == null) {
2960 p = scanPackageLI(fullPath, fullPath, fullPath,
2961 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
2962 PackageParser.PARSE_CHATTY |
2963 PackageParser.PARSE_MUST_BE_APK,
2964 SCAN_MONITOR);
2965 if (p != null) {
2966 synchronized (mPackages) {
2967 grantPermissionsLP(p, false);
2968 }
2969 addedPackage = p.applicationInfo.packageName;
2970 addedUid = p.applicationInfo.uid;
2971 }
2972 }
2973 }
2974
2975 synchronized (mPackages) {
2976 mSettings.writeLP();
2977 }
2978 }
2979
2980 if (removedPackage != null) {
2981 Bundle extras = new Bundle(1);
2982 extras.putInt(Intent.EXTRA_UID, removedUid);
2983 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
2984 }
2985 if (addedPackage != null) {
2986 Bundle extras = new Bundle(1);
2987 extras.putInt(Intent.EXTRA_UID, addedUid);
2988 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
2989 }
2990 }
2991
2992 private final String mRootDir;
2993 private final boolean mIsRom;
2994 }
2995
2996 /* Called when a downloaded package installation has been confirmed by the user */
2997 public void installPackage(
2998 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
2999 mContext.enforceCallingOrSelfPermission(
3000 android.Manifest.permission.INSTALL_PACKAGES, null);
3001
3002 // Queue up an async operation since the package installation may take a little while.
3003 mHandler.post(new Runnable() {
3004 public void run() {
3005 mHandler.removeCallbacks(this);
3006 PackageInstalledInfo res;
3007 synchronized (mInstallLock) {
3008 res = installPackageLI(packageURI, flags);
3009 }
3010 if (observer != null) {
3011 try {
3012 observer.packageInstalled(res.name, res.returnCode);
3013 } catch (RemoteException e) {
3014 Log.i(TAG, "Observer no longer exists.");
3015 }
3016 }
3017 // There appears to be a subtle deadlock condition if the sendPackageBroadcast call appears
3018 // in the synchronized block above.
3019 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3020 res.removedInfo.sendBroadcast();
3021 Bundle extras = new Bundle(1);
3022 extras.putInt(Intent.EXTRA_UID, res.uid);
3023 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3024 res.pkg.applicationInfo.packageName,
3025 extras);
3026 }
3027 Runtime.getRuntime().gc();
3028 }
3029 });
3030 }
3031
3032 class PackageInstalledInfo {
3033 String name;
3034 int uid;
3035 PackageParser.Package pkg;
3036 int returnCode;
3037 PackageRemovedInfo removedInfo;
3038 }
3039
3040 PackageInstalledInfo installPackageLI(Uri packageURI, int flags) {
3041 int returnCode = PackageManager.INSTALL_SUCCEEDED;
3042 String installedPackageName = null;
3043 int installedPackageUid = -1;
3044 PackageParser.Package installedPackage = null;
3045 File tmpPackageFile = null;
3046 boolean wroteSettings = false;
3047 String pkgName = null;
3048 PackageParser.Package newPackage = null;
3049 boolean dataDirExists = false;
3050 PackageParser.Package deletedPackage = null;
3051 PackageRemovedInfo removedInfo = new PackageRemovedInfo();
3052
3053 main_flow: try {
3054 tmpPackageFile = createTempPackageFile();
3055 if (tmpPackageFile == null) {
3056 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3057 break main_flow;
3058 }
3059 tmpPackageFile.deleteOnExit(); // paranoia
3060 if (packageURI.getScheme().equals("file")) {
3061 final File srcPackageFile = new File(packageURI.getPath());
3062 // We copy the source package file to a temp file and then rename it to the
3063 // destination file in order to eliminate a window where the package directory
3064 // scanner notices the new package file but it's not completely copied yet.
3065 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
3066 Log.e(TAG, "Couldn't copy package file to temp file.");
3067 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3068 break main_flow;
3069 }
3070 } else if (packageURI.getScheme().equals("content")) {
3071 ParcelFileDescriptor fd;
3072 try {
3073 fd = mContext.getContentResolver().openFileDescriptor(packageURI, "r");
3074 } catch (FileNotFoundException e) {
3075 Log.e(TAG, "Couldn't open file descriptor from download service.");
3076 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3077 break main_flow;
3078 }
3079 if (fd == null) {
3080 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
3081 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3082 break main_flow;
3083 }
3084 if (Config.LOGV) {
3085 Log.v(TAG, "Opened file descriptor from download service.");
3086 }
3087 ParcelFileDescriptor.AutoCloseInputStream
3088 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
3089 // We copy the source package file to a temp file and then rename it to the
3090 // destination file in order to eliminate a window where the package directory
3091 // scanner notices the new package file but it's not completely copied yet.
3092 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
3093 Log.e(TAG, "Couldn't copy package stream to temp file.");
3094 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3095 break main_flow;
3096 }
3097 } else {
3098 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + packageURI);
3099 returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
3100 break main_flow;
3101 }
3102 pkgName = PackageParser.parsePackageName(
3103 tmpPackageFile.getAbsolutePath(), 0);
3104 if (pkgName == null) {
3105 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
3106 returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3107 break main_flow;
3108 }
3109 //initialize some variables before installing pkg
3110 final String pkgFileName = pkgName + ".apk";
3111 final File destDir = ((flags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
3112 ? mDrmAppPrivateInstallDir
3113 : mAppInstallDir;
3114 final File destPackageFile = new File(destDir, pkgFileName);
3115 final String destFilePath = destPackageFile.getAbsolutePath();
3116 File destResourceFile;
3117 if ((flags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
3118 final String publicZipFileName = pkgName + ".zip";
3119 destResourceFile = new File(mAppInstallDir, publicZipFileName);
3120 } else {
3121 destResourceFile = destPackageFile;
3122 }
3123 //retrieve PackageSettings and parse package
3124 int parseFlags = PackageParser.PARSE_CHATTY;
3125 parseFlags |= mDefParseFlags;
3126 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
3127 pp.setSeparateProcesses(mSeparateProcesses);
3128 pp.setSdkVersion(mSdkVersion);
3129 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
3130 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
3131 if (pkg == null) {
3132 returnCode = pp.getParseError();
3133 break main_flow;
3134 }
3135 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
3136 returnCode = pp.getParseError();
3137 break main_flow;
3138 }
3139
3140 boolean replacingExistingPackage = false;
3141
3142 synchronized (mPackages) {
3143 //check if installing already existing package
3144 if ((flags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
3145 && mPackages.containsKey(pkgName)) {
3146 replacingExistingPackage = true;
3147 deletedPackage = mPackages.get(pkgName);
3148 if(checkSignaturesLP(pkg, deletedPackage) != PackageManager.SIGNATURE_MATCH) {
3149 returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3150 break main_flow;
3151 }
3152 }
3153 }
3154
3155 if (replacingExistingPackage) {
3156 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3157 removedInfo)) {
3158 returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3159 break main_flow;
3160 }
3161 } else {
3162 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3163 // Don't allow installation over an existing package with the same name.
3164 Log.w(TAG, "Attempt to re-install " + pkgName
3165 + " without first uninstalling.");
3166 returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3167 break main_flow;
3168 }
3169 if (destPackageFile.exists()) {
3170 // It's safe to do this because we know (from the above check) that the file
3171 // isn't currently used for an installed package.
3172 destPackageFile.delete();
3173 }
3174 }
3175
3176 // Remember this for later, in case we need to rollback this install
3177 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3178 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3179 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3180 destResourceFile, pkg, parseFlags,
3181 SCAN_MONITOR | SCAN_FORCE_DEX
3182 | (!replacingExistingPackage ? SCAN_UPDATE_SIGNATURE : 0)
3183 | ((flags&PackageManager.FORWARD_LOCK_PACKAGE) != 0
3184 ? SCAN_FORWARD_LOCKED : 0));
3185 if (newPackage == null) {
3186 if (Config.LOGD) {
3187 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3188 }
3189 if ((returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3190 returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3191 }
3192 break main_flow;
3193 }
3194
3195 synchronized (mPackages) {
3196 //write settings. the installStatus will be incomplete at this stage.
3197 //note that the new package setting would have already been
3198 //added to mPackages. It hasn't been persisted yet.
3199 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
3200 mSettings.writeLP();
3201 wroteSettings = true;
3202 }
3203
3204 int retCode = 0;
3205 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
3206 retCode = mInstaller.movedex(tmpPackageFile.toString(),
3207 destPackageFile.toString());
3208 if (retCode != 0) {
3209 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
3210 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3211 break main_flow;
3212 }
3213 }
3214 // XXX There are probably some big issues here: upon doing
3215 // the rename, we have reached the point of no return (the
3216 // original .apk is gone!), so we can't fail. Yet... we can.
3217 if (tmpPackageFile.renameTo(destPackageFile)) {
3218 if ((flags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
3219 try {
3220 extractPublicFiles(newPackage, destResourceFile);
3221 } catch (IOException e) {
3222 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
3223 " forward-locked app.");
3224 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3225 break main_flow;
3226 }
3227 if (mInstaller != null) {
3228 retCode = mInstaller.setForwardLockPerm(pkgName,
3229 newPackage.applicationInfo.uid);
3230 } else {
3231 final int filePermissions =
3232 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
3233 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
3234 newPackage.applicationInfo.uid);
3235 }
3236 } else {
3237 final int filePermissions =
3238 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3239 |FileUtils.S_IROTH;
3240 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
3241 }
3242 if (retCode != 0) {
3243 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
3244 + ". The return code was: " + retCode);
3245 }
3246 if (Config.LOGD) {
3247 Log.d(TAG, "New package installed in " + destPackageFile);
3248 }
3249
3250 synchronized (mPackages) {
3251 grantPermissionsLP(newPackage, true);
3252 installedPackageName = pkgName;
3253 installedPackageUid = newPackage.applicationInfo.uid;
3254 installedPackage = newPackage;
3255 if(replacingExistingPackage) {
3256 //update signature on the new package setting
3257 //this should always succeed, since we checked the
3258 //signature earlier.
3259 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3260 parseFlags, true);
3261 }
3262 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
3263 returnCode = PackageManager.INSTALL_SUCCEEDED;
3264 //to update install status
3265 mSettings.writeLP();
3266 break main_flow;
3267 }
3268 } else {
3269 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
3270 returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3271 break main_flow;
3272 }
3273 } finally {
3274 if (tmpPackageFile != null && tmpPackageFile.exists()) {
3275 tmpPackageFile.delete();
3276 }
3277
3278 //if install was successful the pkg's installStatus would have
3279 //been updated and hence needs to be persisted. if not
3280 //the pkg info needs to be cleaned up.
3281 if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
3282 if (deletedPackage != null) {
3283 // If we deleted an exisiting package, the old source and resource files that we
3284 // were keeping around in case we needed them (see below) can now be deleted
3285 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3286 final ApplicationInfo installedPackageAppInfo =
3287 installedPackage.applicationInfo;
3288 if (!deletedPackageAppInfo.sourceDir
3289 .equals(installedPackageAppInfo.sourceDir)) {
3290 new File(deletedPackageAppInfo.sourceDir).delete();
3291 }
3292 if (!deletedPackageAppInfo.publicSourceDir
3293 .equals(installedPackageAppInfo.publicSourceDir)) {
3294 new File(deletedPackageAppInfo.publicSourceDir).delete();
3295 }
3296 }
3297 } else {
3298 if (mInstaller != null) {
3299 mInstaller.rmdex(tmpPackageFile.getPath());
3300 }
3301 if (wroteSettings) {
3302 // remove package from internal structures. Note that we want deletePackageX to
3303 // delete the package data and cache directories that it created in
3304 // scanPackageLocked, unless those directories existed before we even tried to
3305 // install.
3306 deletePackageLI(
3307 pkgName, true,
3308 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3309 new PackageRemovedInfo());
3310 if (deletedPackage != null) {
3311 // Since we failed to install the new package we need to restore the old
3312 // package that we deleted.
3313 installPackageLI(
3314 Uri.fromFile(new File(deletedPackage.mPath)),
3315 isForwardLocked(deletedPackage)
3316 ? PackageManager.FORWARD_LOCK_PACKAGE
3317 : 0);
3318 }
3319 }
3320 }
3321 }
3322
3323 PackageInstalledInfo res = new PackageInstalledInfo();
3324 res.name = installedPackageName;
3325 res.uid = installedPackageUid;
3326 res.pkg = installedPackage;
3327 res.returnCode = returnCode;
3328 res.removedInfo = removedInfo;
3329 return res;
3330 }
3331
3332 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
3333 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
3334 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
3335 }
3336
3337 private void extractPublicFiles(PackageParser.Package newPackage,
3338 File publicZipFile) throws IOException {
3339 final ZipOutputStream publicZipOutStream =
3340 new ZipOutputStream(new FileOutputStream(publicZipFile));
3341 final ZipFile privateZip = new ZipFile(newPackage.mPath);
3342
3343 // Copy manifest, resources.arsc and res directory to public zip
3344
3345 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
3346 while (privateZipEntries.hasMoreElements()) {
3347 final ZipEntry zipEntry = privateZipEntries.nextElement();
3348 final String zipEntryName = zipEntry.getName();
3349 if ("AndroidManifest.xml".equals(zipEntryName)
3350 || "resources.arsc".equals(zipEntryName)
3351 || zipEntryName.startsWith("res/")) {
3352 try {
3353 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
3354 } catch (IOException e) {
3355 try {
3356 publicZipOutStream.close();
3357 throw e;
3358 } finally {
3359 publicZipFile.delete();
3360 }
3361 }
3362 }
3363 }
3364
3365 publicZipOutStream.close();
3366 FileUtils.setPermissions(
3367 publicZipFile.getAbsolutePath(),
3368 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
3369 -1, -1);
3370 }
3371
3372 private static void copyZipEntry(ZipEntry zipEntry,
3373 ZipFile inZipFile,
3374 ZipOutputStream outZipStream) throws IOException {
3375 byte[] buffer = new byte[4096];
3376 int num;
3377
3378 ZipEntry newEntry;
3379 if (zipEntry.getMethod() == ZipEntry.STORED) {
3380 // Preserve the STORED method of the input entry.
3381 newEntry = new ZipEntry(zipEntry);
3382 } else {
3383 // Create a new entry so that the compressed len is recomputed.
3384 newEntry = new ZipEntry(zipEntry.getName());
3385 }
3386 outZipStream.putNextEntry(newEntry);
3387
3388 InputStream data = inZipFile.getInputStream(zipEntry);
3389 while ((num = data.read(buffer)) > 0) {
3390 outZipStream.write(buffer, 0, num);
3391 }
3392 outZipStream.flush();
3393 }
3394
3395 private void deleteTempPackageFiles() {
3396 FilenameFilter filter = new FilenameFilter() {
3397 public boolean accept(File dir, String name) {
3398 return name.startsWith("vmdl") && name.endsWith(".tmp");
3399 }
3400 };
3401 String tmpFilesList[] = mAppInstallDir.list(filter);
3402 if(tmpFilesList == null) {
3403 return;
3404 }
3405 for(int i = 0; i < tmpFilesList.length; i++) {
3406 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
3407 tmpFile.delete();
3408 }
3409 }
3410
3411 private File createTempPackageFile() {
3412 File tmpPackageFile;
3413 try {
3414 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
3415 } catch (IOException e) {
3416 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
3417 return null;
3418 }
3419 try {
3420 FileUtils.setPermissions(
3421 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
3422 -1, -1);
3423 } catch (IOException e) {
3424 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
3425 return null;
3426 }
3427 return tmpPackageFile;
3428 }
3429
3430 public void deletePackage(final String packageName,
3431 final IPackageDeleteObserver observer,
3432 final int flags) {
3433 mContext.enforceCallingOrSelfPermission(
3434 android.Manifest.permission.DELETE_PACKAGES, null);
3435 // Queue up an async operation since the package deletion may take a little while.
3436 mHandler.post(new Runnable() {
3437 public void run() {
3438 mHandler.removeCallbacks(this);
3439 final boolean succeded = deletePackageX(packageName, true, true, flags);
3440 if (observer != null) {
3441 try {
3442 observer.packageDeleted(succeded);
3443 } catch (RemoteException e) {
3444 Log.i(TAG, "Observer no longer exists.");
3445 } //end catch
3446 } //end if
3447 } //end run
3448 });
3449 }
3450
3451 /**
3452 * This method is an internal method that could be get invoked either
3453 * to delete an installed package or to clean up a failed installation.
3454 * After deleting an installed package, a broadcast is sent to notify any
3455 * listeners that the package has been installed. For cleaning up a failed
3456 * installation, the broadcast is not necessary since the package's
3457 * installation wouldn't have sent the initial broadcast either
3458 * The key steps in deleting a package are
3459 * deleting the package information in internal structures like mPackages,
3460 * deleting the packages base directories through installd
3461 * updating mSettings to reflect current status
3462 * persisting settings for later use
3463 * sending a broadcast if necessary
3464 */
3465
3466 private boolean deletePackageX(String packageName, boolean sendBroadCast,
3467 boolean deleteCodeAndResources, int flags) {
3468 PackageRemovedInfo info = new PackageRemovedInfo();
3469 boolean res = false;
3470
3471 synchronized (mInstallLock) {
3472 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
3473 if (res) {
3474 synchronized (mPackages) {
3475 mSettings.writeLP();
3476 }
3477 }
3478 }
3479
3480 if(res && sendBroadCast) {
3481 info.sendBroadcast();
3482 }
3483 return res;
3484 }
3485
3486 static class PackageRemovedInfo {
3487 String removedPackage;
3488 int uid = -1;
3489 int removedUid = -1;
3490
3491 void sendBroadcast() {
3492 Bundle extras = new Bundle(1);
3493 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
3494 if (removedPackage != null) {
3495 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3496 }
3497 if (removedUid >= 0) {
3498 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
3499 }
3500 }
3501 }
3502
3503 private boolean deletePackageLI(String packageName,
3504 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
3505 if (packageName == null) {
3506 Log.w(TAG, "Attempt to delete null packageName.");
3507 return false;
3508 }
3509 PackageParser.Package p;
3510 synchronized (mPackages) {
3511 p = mPackages.get(packageName);
3512 }
3513 if (p == null) {
3514 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
3515 return false;
3516 }
3517 final ApplicationInfo applicationInfo = p.applicationInfo;
3518 if (applicationInfo == null) {
3519 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
3520 return false;
3521 }
3522
3523 // NB: This is a public nonfinal boolean so it theoretically
3524 // could be altered by anyone. In practice, that can only be
3525 // done from within this same process, and anyway file
3526 // permissions will prevent unauthorized deletion of system
3527 // packages.
3528 if ((applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3529 Log.w(TAG, "Attempt to delete system package "+ packageName);
3530 return false;
3531 }
3532 final File sourceFile = new File(applicationInfo.sourceDir);
3533 if (!sourceFile.exists()) {
3534 Log.w(TAG, "Package source " + applicationInfo.sourceDir + " does not exist.");
3535 return false;
3536 }
3537 outInfo.uid = p.applicationInfo.uid;
3538
3539 outInfo.removedPackage = packageName;
3540 removePackageLI(p, true);
3541 if (deleteCodeAndResources) {
3542 sourceFile.delete();
3543 final File publicSourceFile = new File(applicationInfo.publicSourceDir);
3544 if (publicSourceFile.exists()) {
3545 publicSourceFile.delete();
3546 }
3547 if (mInstaller != null) {
3548 int retCode = mInstaller.rmdex(sourceFile.toString());
3549 if (retCode < 0) {
3550 Log.w(TAG, "Couldn't remove dex file for package: "
3551 + packageName + ", retcode=" + retCode);
3552 // we don't consider this to be a failure of the core package deletion
3553 }
3554 }
3555 }
3556 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
3557 if (mInstaller != null) {
3558 int retCode = mInstaller.remove(packageName);
3559 if (retCode < 0) {
3560 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
3561 + packageName + ", retcode=" + retCode);
3562 // we don't consider this to be a failure of the core package deletion
3563 }
3564 } else {
3565 //for emulator
3566 PackageParser.Package pkg = mPackages.get(packageName);
3567 File dataDir = new File(pkg.applicationInfo.dataDir);
3568 dataDir.delete();
3569 }
3570 synchronized (mPackages) {
3571 outInfo.removedUid = mSettings.removePackageLP(packageName);
3572 }
3573 }
3574 return true;
3575 }
3576
3577 public void clearApplicationUserData(final String packageName,
3578 final IPackageDataObserver observer) {
3579 mContext.enforceCallingOrSelfPermission(
3580 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
3581 // Queue up an async operation since the package deletion may take a little while.
3582 mHandler.post(new Runnable() {
3583 public void run() {
3584 mHandler.removeCallbacks(this);
3585 final boolean succeded;
3586 synchronized (mInstallLock) {
3587 succeded = clearApplicationUserDataLI(packageName);
3588 }
3589 if(succeded) {
3590 //invoke DeviceMemoryMonitor's update method to clear any notifications
3591 DeviceMemoryMonitorService dmm = (DeviceMemoryMonitorService)
3592 ServiceManager.getService("devicememorymonitor");
3593 if(dmm!=null) {
3594 dmm.updateMemory();
3595 }
3596 }
3597 if(observer != null) {
3598 try {
3599 observer.onRemoveCompleted(packageName, succeded);
3600 } catch (RemoteException e) {
3601 Log.i(TAG, "Observer no longer exists.");
3602 }
3603 } //end if observer
3604 } //end run
3605 });
3606 }
3607
3608 private boolean clearApplicationUserDataLI(String packageName) {
3609 if (packageName == null) {
3610 Log.w(TAG, "Attempt to delete null packageName.");
3611 return false;
3612 }
3613 PackageParser.Package p;
3614 synchronized (mPackages) {
3615 p = mPackages.get(packageName);
3616 }
3617 if (p == null) {
3618 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
3619 return false;
3620 }
3621 final ApplicationInfo applicationInfo = p.applicationInfo;
3622 if (applicationInfo == null) {
3623 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
3624 return false;
3625 }
3626 if (mInstaller != null) {
3627 int retCode = mInstaller.clearUserData(packageName);
3628 if (retCode < 0) {
3629 Log.w(TAG, "Couldn't remove cache files for package: "
3630 + packageName);
3631 return false;
3632 }
3633 }
3634 return true;
3635 }
3636
3637 public void deleteApplicationCacheFiles(final String packageName,
3638 final IPackageDataObserver observer) {
3639 mContext.enforceCallingOrSelfPermission(
3640 android.Manifest.permission.DELETE_CACHE_FILES, null);
3641 // Queue up an async operation since the package deletion may take a little while.
3642 mHandler.post(new Runnable() {
3643 public void run() {
3644 mHandler.removeCallbacks(this);
3645 final boolean succeded;
3646 synchronized (mInstallLock) {
3647 succeded = deleteApplicationCacheFilesLI(packageName);
3648 }
3649 if(observer != null) {
3650 try {
3651 observer.onRemoveCompleted(packageName, succeded);
3652 } catch (RemoteException e) {
3653 Log.i(TAG, "Observer no longer exists.");
3654 }
3655 } //end if observer
3656 } //end run
3657 });
3658 }
3659
3660 private boolean deleteApplicationCacheFilesLI(String packageName) {
3661 if (packageName == null) {
3662 Log.w(TAG, "Attempt to delete null packageName.");
3663 return false;
3664 }
3665 PackageParser.Package p;
3666 synchronized (mPackages) {
3667 p = mPackages.get(packageName);
3668 }
3669 if (p == null) {
3670 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
3671 return false;
3672 }
3673 final ApplicationInfo applicationInfo = p.applicationInfo;
3674 if (applicationInfo == null) {
3675 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
3676 return false;
3677 }
3678 if (mInstaller != null) {
3679 int retCode = mInstaller.deleteCacheFiles(packageName);
3680 if (retCode < 0) {
3681 Log.w(TAG, "Couldn't remove cache files for package: "
3682 + packageName);
3683 return false;
3684 }
3685 }
3686 return true;
3687 }
3688
3689 public void getPackageSizeInfo(final String packageName,
3690 final IPackageStatsObserver observer) {
3691 mContext.enforceCallingOrSelfPermission(
3692 android.Manifest.permission.GET_PACKAGE_SIZE, null);
3693 // Queue up an async operation since the package deletion may take a little while.
3694 mHandler.post(new Runnable() {
3695 public void run() {
3696 mHandler.removeCallbacks(this);
3697 PackageStats lStats = new PackageStats(packageName);
3698 final boolean succeded;
3699 synchronized (mInstallLock) {
3700 succeded = getPackageSizeInfoLI(packageName, lStats);
3701 }
3702 if(observer != null) {
3703 try {
3704 observer.onGetStatsCompleted(lStats, succeded);
3705 } catch (RemoteException e) {
3706 Log.i(TAG, "Observer no longer exists.");
3707 }
3708 } //end if observer
3709 } //end run
3710 });
3711 }
3712
3713 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
3714 if (packageName == null) {
3715 Log.w(TAG, "Attempt to get size of null packageName.");
3716 return false;
3717 }
3718 PackageParser.Package p;
3719 synchronized (mPackages) {
3720 p = mPackages.get(packageName);
3721 }
3722 if (p == null) {
3723 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
3724 return false;
3725 }
3726 final ApplicationInfo applicationInfo = p.applicationInfo;
3727 if (applicationInfo == null) {
3728 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
3729 return false;
3730 }
3731 if (mInstaller != null) {
3732 int res = mInstaller.getSizeInfo(packageName, p.mPath,
3733 isForwardLocked(p) ? applicationInfo.publicSourceDir : null,
3734 pStats);
3735 if (res < 0) {
3736 return false;
3737 } else {
3738 return true;
3739 }
3740 }
3741 return true;
3742 }
3743
3744
3745 public void addPackageToPreferred(String packageName) {
3746 mContext.enforceCallingOrSelfPermission(
3747 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
3748
3749 synchronized (mPackages) {
3750 PackageParser.Package p = mPackages.get(packageName);
3751 if (p == null) {
3752 return;
3753 }
3754 PackageSetting ps = (PackageSetting)p.mExtras;
3755 if (ps != null) {
3756 mSettings.mPreferredPackages.remove(ps);
3757 mSettings.mPreferredPackages.add(0, ps);
3758 updatePreferredIndicesLP();
3759 mSettings.writeLP();
3760 }
3761 }
3762 }
3763
3764 public void removePackageFromPreferred(String packageName) {
3765 mContext.enforceCallingOrSelfPermission(
3766 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
3767
3768 synchronized (mPackages) {
3769 PackageParser.Package p = mPackages.get(packageName);
3770 if (p == null) {
3771 return;
3772 }
3773 if (p.mPreferredOrder > 0) {
3774 PackageSetting ps = (PackageSetting)p.mExtras;
3775 if (ps != null) {
3776 mSettings.mPreferredPackages.remove(ps);
3777 p.mPreferredOrder = 0;
3778 updatePreferredIndicesLP();
3779 mSettings.writeLP();
3780 }
3781 }
3782 }
3783 }
3784
3785 private void updatePreferredIndicesLP() {
3786 final ArrayList<PackageSetting> pkgs
3787 = mSettings.mPreferredPackages;
3788 final int N = pkgs.size();
3789 for (int i=0; i<N; i++) {
3790 pkgs.get(i).pkg.mPreferredOrder = N - i;
3791 }
3792 }
3793
3794 public List<PackageInfo> getPreferredPackages(int flags) {
3795 synchronized (mPackages) {
3796 final ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
3797 final ArrayList<PackageSetting> pref = mSettings.mPreferredPackages;
3798 final int N = pref.size();
3799 for (int i=0; i<N; i++) {
3800 res.add(generatePackageInfo(pref.get(i).pkg, flags));
3801 }
3802 return res;
3803 }
3804 }
3805
3806 public void addPreferredActivity(IntentFilter filter, int match,
3807 ComponentName[] set, ComponentName activity) {
3808 mContext.enforceCallingOrSelfPermission(
3809 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
3810
3811 synchronized (mPackages) {
3812 Log.i(TAG, "Adding preferred activity " + activity + ":");
3813 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
3814 mSettings.mPreferredActivities.addFilter(
3815 new PreferredActivity(filter, match, set, activity));
3816 mSettings.writeLP();
3817 }
3818 }
3819
3820 public void clearPackagePreferredActivities(String packageName) {
3821 mContext.enforceCallingOrSelfPermission(
3822 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
3823
3824 synchronized (mPackages) {
3825 if (clearPackagePreferredActivitiesLP(packageName)) {
3826 mSettings.writeLP();
3827 }
3828 }
3829 }
3830
3831 boolean clearPackagePreferredActivitiesLP(String packageName) {
3832 boolean changed = false;
3833 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
3834 while (it.hasNext()) {
3835 PreferredActivity pa = it.next();
3836 if (pa.mActivity.getPackageName().equals(packageName)) {
3837 it.remove();
3838 changed = true;
3839 }
3840 }
3841 return changed;
3842 }
3843
3844 public int getPreferredActivities(List<IntentFilter> outFilters,
3845 List<ComponentName> outActivities, String packageName) {
3846
3847 int num = 0;
3848 synchronized (mPackages) {
3849 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
3850 while (it.hasNext()) {
3851 PreferredActivity pa = it.next();
3852 if (packageName == null
3853 || pa.mActivity.getPackageName().equals(packageName)) {
3854 if (outFilters != null) {
3855 outFilters.add(new IntentFilter(pa));
3856 }
3857 if (outActivities != null) {
3858 outActivities.add(pa.mActivity);
3859 }
3860 }
3861 }
3862 }
3863
3864 return num;
3865 }
3866
3867 public void setApplicationEnabledSetting(String appPackageName,
3868 int newState, int flags) {
3869 setEnabledSetting(appPackageName, null, newState, flags);
3870 }
3871
3872 public void setComponentEnabledSetting(ComponentName componentName,
3873 int newState, int flags) {
3874 setEnabledSetting(componentName.getPackageName(),
3875 componentName.getClassName(), newState, flags);
3876 }
3877
3878 private void setEnabledSetting(
3879 final String packageNameStr, String classNameStr, int newState, final int flags) {
3880 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
3881 || newState == COMPONENT_ENABLED_STATE_ENABLED
3882 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
3883 throw new IllegalArgumentException("Invalid new component state: "
3884 + newState);
3885 }
3886 PackageSetting pkgSetting;
3887 final int uid = Binder.getCallingUid();
3888 final int permission = mContext.checkCallingPermission(
3889 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
3890 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
3891 int packageUid = -1;
3892 synchronized (mPackages) {
3893 pkgSetting = mSettings.mPackages.get(packageNameStr);
3894 if (pkgSetting == null) {
3895 if (classNameStr == null) {
3896 throw new IllegalArgumentException(
3897 "Unknown package: " + packageNameStr);
3898 }
3899 throw new IllegalArgumentException(
3900 "Unknown component: " + packageNameStr
3901 + "/" + classNameStr);
3902 }
3903 if (!allowedByPermission && (uid != pkgSetting.userId)) {
3904 throw new SecurityException(
3905 "Permission Denial: attempt to change component state from pid="
3906 + Binder.getCallingPid()
3907 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
3908 }
3909 packageUid = pkgSetting.userId;
3910 if (classNameStr == null) {
3911 // We're dealing with an application/package level state change
3912 pkgSetting.enabled = newState;
3913 } else {
3914 // We're dealing with a component level state change
3915 switch (newState) {
3916 case COMPONENT_ENABLED_STATE_ENABLED:
3917 pkgSetting.enableComponentLP(classNameStr);
3918 break;
3919 case COMPONENT_ENABLED_STATE_DISABLED:
3920 pkgSetting.disableComponentLP(classNameStr);
3921 break;
3922 case COMPONENT_ENABLED_STATE_DEFAULT:
3923 pkgSetting.restoreComponentLP(classNameStr);
3924 break;
3925 default:
3926 Log.e(TAG, "Invalid new component state: " + newState);
3927 }
3928 }
3929 mSettings.writeLP();
3930 }
3931
3932 long callingId = Binder.clearCallingIdentity();
3933 try {
3934 Bundle extras = new Bundle(2);
3935 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP,
3936 (flags&PackageManager.DONT_KILL_APP) != 0);
3937 extras.putInt(Intent.EXTRA_UID, packageUid);
3938 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageNameStr, extras);
3939 } finally {
3940 Binder.restoreCallingIdentity(callingId);
3941 }
3942 }
3943
3944 public int getApplicationEnabledSetting(String appPackageName) {
3945 synchronized (mPackages) {
3946 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
3947 if (pkg == null) {
3948 throw new IllegalArgumentException("Unknown package: " + appPackageName);
3949 }
3950 return pkg.enabled;
3951 }
3952 }
3953
3954 public int getComponentEnabledSetting(ComponentName componentName) {
3955 synchronized (mPackages) {
3956 final String packageNameStr = componentName.getPackageName();
3957 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
3958 if (pkg == null) {
3959 throw new IllegalArgumentException("Unknown component: " + componentName);
3960 }
3961 final String classNameStr = componentName.getClassName();
3962 return pkg.currentEnabledStateLP(classNameStr);
3963 }
3964 }
3965
3966 public void enterSafeMode() {
3967 if (!mSystemReady) {
3968 mSafeMode = true;
3969 }
3970 }
3971
3972 public void systemReady() {
3973 mSystemReady = true;
3974 }
3975
3976 public boolean hasSystemUidErrors() {
3977 return mHasSystemUidErrors;
3978 }
3979
3980 static String arrayToString(int[] array) {
3981 StringBuffer buf = new StringBuffer(128);
3982 buf.append('[');
3983 if (array != null) {
3984 for (int i=0; i<array.length; i++) {
3985 if (i > 0) buf.append(", ");
3986 buf.append(array[i]);
3987 }
3988 }
3989 buf.append(']');
3990 return buf.toString();
3991 }
3992
3993 @Override
3994 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3995 if (mContext.checkCallingPermission(android.Manifest.permission.DUMP)
3996 != PackageManager.PERMISSION_GRANTED) {
3997 pw.println("Permission Denial: can't dump ActivityManager from from pid="
3998 + Binder.getCallingPid()
3999 + ", uid=" + Binder.getCallingUid()
4000 + " without permission "
4001 + android.Manifest.permission.DUMP);
4002 return;
4003 }
4004
4005 Printer printer = new PrintWriterPrinter(pw);
4006 synchronized (mPackages) {
4007 pw.println("Activity Resolver Table:");
4008 mActivities.dump(printer, " ");
4009 pw.println(" ");
4010 pw.println("Receiver Resolver Table:");
4011 mReceivers.dump(printer, " ");
4012 pw.println(" ");
4013 pw.println("Service Resolver Table:");
4014 mServices.dump(printer, " ");
4015 pw.println(" ");
4016 pw.println("Preferred Activities:");
4017 mSettings.mPreferredActivities.dump(printer, " ");
4018 pw.println(" ");
4019 pw.println("Preferred Packages:");
4020 {
4021 for (PackageSetting ps : mSettings.mPreferredPackages) {
4022 pw.println(" " + ps.name);
4023 }
4024 }
4025 pw.println(" ");
4026 pw.println("Permissions:");
4027 {
4028 for (BasePermission p : mSettings.mPermissions.values()) {
4029 pw.println(" Permission [" + p.name + "] ("
4030 + Integer.toHexString(System.identityHashCode(p))
4031 + "):");
4032 pw.println(" sourcePackage=" + p.sourcePackage);
4033 pw.println(" uid=" + p.uid
4034 + " gids=" + arrayToString(p.gids)
4035 + " type=" + p.type);
4036 }
4037 }
4038 pw.println(" ");
4039 pw.println("Packages:");
4040 {
4041 for (PackageSetting ps : mSettings.mPackages.values()) {
4042 pw.println(" Package [" + ps.name + "] ("
4043 + Integer.toHexString(System.identityHashCode(ps))
4044 + "):");
4045 pw.println(" userId=" + ps.userId
4046 + " gids=" + arrayToString(ps.gids));
4047 pw.println(" sharedUser=" + ps.sharedUser);
4048 pw.println(" pkg=" + ps.pkg);
4049 pw.println(" codePath=" + ps.codePathString);
4050 pw.println(" resourcePath=" + ps.resourcePathString);
4051 if (ps.pkg != null) {
4052 pw.println(" dataDir=" + ps.pkg.applicationInfo.dataDir);
4053 }
4054 pw.println(" timeStamp=" + ps.timeStamp);
4055 pw.println(" signatures=" + ps.signatures);
4056 pw.println(" permissionsFixed=" + ps.permissionsFixed
4057 + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags)
4058 + " installStatus=" + ps.installStatus
4059 + " enabled=" + ps.enabled);
4060 if (ps.disabledComponents.size() > 0) {
4061 pw.println(" disabledComponents:");
4062 for (String s : ps.disabledComponents) {
4063 pw.println(" " + s);
4064 }
4065 }
4066 if (ps.enabledComponents.size() > 0) {
4067 pw.println(" enabledComponents:");
4068 for (String s : ps.enabledComponents) {
4069 pw.println(" " + s);
4070 }
4071 }
4072 pw.println(" grantedPermissions:");
4073 for (String s : ps.grantedPermissions) {
4074 pw.println(" " + s);
4075 }
4076 pw.println(" loadedPermissions:");
4077 for (String s : ps.loadedPermissions) {
4078 pw.println(" " + s);
4079 }
4080 }
4081 }
4082 pw.println(" ");
4083 pw.println("Shared Users:");
4084 {
4085 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
4086 pw.println(" SharedUser [" + su.name + "] ("
4087 + Integer.toHexString(System.identityHashCode(su))
4088 + "):");
4089 pw.println(" userId=" + su.userId
4090 + " gids=" + arrayToString(su.gids));
4091 pw.println(" grantedPermissions:");
4092 for (String s : su.grantedPermissions) {
4093 pw.println(" " + s);
4094 }
4095 pw.println(" loadedPermissions:");
4096 for (String s : su.loadedPermissions) {
4097 pw.println(" " + s);
4098 }
4099 }
4100 }
4101 pw.println(" ");
4102 pw.println("Settings parse messages:");
4103 pw.println(mSettings.mReadMessages.toString());
4104 }
4105 }
4106
4107 static final class BasePermission {
4108 final static int TYPE_NORMAL = 0;
4109 final static int TYPE_BUILTIN = 1;
4110 final static int TYPE_DYNAMIC = 2;
4111
4112 final String name;
4113 final String sourcePackage;
4114 final int type;
4115 PackageParser.Permission perm;
4116 PermissionInfo pendingInfo;
4117 int uid;
4118 int[] gids;
4119
4120 BasePermission(String _name, String _sourcePackage, int _type) {
4121 name = _name;
4122 sourcePackage = _sourcePackage;
4123 type = _type;
4124 }
4125 }
4126
4127 static class PackageSignatures {
4128 private Signature[] mSignatures;
4129
4130 PackageSignatures(Signature[] sigs) {
4131 assignSignatures(sigs);
4132 }
4133
4134 PackageSignatures() {
4135 }
4136
4137 void writeXml(XmlSerializer serializer, String tagName,
4138 ArrayList<Signature> pastSignatures) throws IOException {
4139 if (mSignatures == null) {
4140 return;
4141 }
4142 serializer.startTag(null, tagName);
4143 serializer.attribute(null, "count",
4144 Integer.toString(mSignatures.length));
4145 for (int i=0; i<mSignatures.length; i++) {
4146 serializer.startTag(null, "cert");
4147 final Signature sig = mSignatures[i];
4148 final int sigHash = sig.hashCode();
4149 final int numPast = pastSignatures.size();
4150 int j;
4151 for (j=0; j<numPast; j++) {
4152 Signature pastSig = pastSignatures.get(j);
4153 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
4154 serializer.attribute(null, "index", Integer.toString(j));
4155 break;
4156 }
4157 }
4158 if (j >= numPast) {
4159 pastSignatures.add(sig);
4160 serializer.attribute(null, "index", Integer.toString(numPast));
4161 serializer.attribute(null, "key", sig.toCharsString());
4162 }
4163 serializer.endTag(null, "cert");
4164 }
4165 serializer.endTag(null, tagName);
4166 }
4167
4168 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
4169 throws IOException, XmlPullParserException {
4170 String countStr = parser.getAttributeValue(null, "count");
4171 if (countStr == null) {
4172 reportSettingsProblem(Log.WARN,
4173 "Error in package manager settings: <signatures> has"
4174 + " no count at " + parser.getPositionDescription());
4175 XmlUtils.skipCurrentTag(parser);
4176 }
4177 final int count = Integer.parseInt(countStr);
4178 mSignatures = new Signature[count];
4179 int pos = 0;
4180
4181 int outerDepth = parser.getDepth();
4182 int type;
4183 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4184 && (type != XmlPullParser.END_TAG
4185 || parser.getDepth() > outerDepth)) {
4186 if (type == XmlPullParser.END_TAG
4187 || type == XmlPullParser.TEXT) {
4188 continue;
4189 }
4190
4191 String tagName = parser.getName();
4192 if (tagName.equals("cert")) {
4193 if (pos < count) {
4194 String index = parser.getAttributeValue(null, "index");
4195 if (index != null) {
4196 try {
4197 int idx = Integer.parseInt(index);
4198 String key = parser.getAttributeValue(null, "key");
4199 if (key == null) {
4200 if (idx >= 0 && idx < pastSignatures.size()) {
4201 Signature sig = pastSignatures.get(idx);
4202 if (sig != null) {
4203 mSignatures[pos] = pastSignatures.get(idx);
4204 pos++;
4205 } else {
4206 reportSettingsProblem(Log.WARN,
4207 "Error in package manager settings: <cert> "
4208 + "index " + index + " is not defined at "
4209 + parser.getPositionDescription());
4210 }
4211 } else {
4212 reportSettingsProblem(Log.WARN,
4213 "Error in package manager settings: <cert> "
4214 + "index " + index + " is out of bounds at "
4215 + parser.getPositionDescription());
4216 }
4217 } else {
4218 while (pastSignatures.size() <= idx) {
4219 pastSignatures.add(null);
4220 }
4221 Signature sig = new Signature(key);
4222 pastSignatures.set(idx, sig);
4223 mSignatures[pos] = sig;
4224 pos++;
4225 }
4226 } catch (NumberFormatException e) {
4227 reportSettingsProblem(Log.WARN,
4228 "Error in package manager settings: <cert> "
4229 + "index " + index + " is not a number at "
4230 + parser.getPositionDescription());
4231 }
4232 } else {
4233 reportSettingsProblem(Log.WARN,
4234 "Error in package manager settings: <cert> has"
4235 + " no index at " + parser.getPositionDescription());
4236 }
4237 } else {
4238 reportSettingsProblem(Log.WARN,
4239 "Error in package manager settings: too "
4240 + "many <cert> tags, expected " + count
4241 + " at " + parser.getPositionDescription());
4242 }
4243 } else {
4244 reportSettingsProblem(Log.WARN,
4245 "Unknown element under <cert>: "
4246 + parser.getName());
4247 }
4248 XmlUtils.skipCurrentTag(parser);
4249 }
4250
4251 if (pos < count) {
4252 // Should never happen -- there is an error in the written
4253 // settings -- but if it does we don't want to generate
4254 // a bad array.
4255 Signature[] newSigs = new Signature[pos];
4256 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
4257 mSignatures = newSigs;
4258 }
4259 }
4260
4261 /**
4262 * If any of the given 'sigs' is contained in the existing signatures,
4263 * then completely replace the current signatures with the ones in
4264 * 'sigs'. This is used for updating an existing package to a newly
4265 * installed version.
4266 */
4267 boolean updateSignatures(Signature[] sigs, boolean update) {
4268 if (mSignatures == null) {
4269 if (update) {
4270 assignSignatures(sigs);
4271 }
4272 return true;
4273 }
4274 if (sigs == null) {
4275 return false;
4276 }
4277
4278 for (int i=0; i<sigs.length; i++) {
4279 Signature sig = sigs[i];
4280 for (int j=0; j<mSignatures.length; j++) {
4281 if (mSignatures[j].equals(sig)) {
4282 if (update) {
4283 assignSignatures(sigs);
4284 }
4285 return true;
4286 }
4287 }
4288 }
4289 return false;
4290 }
4291
4292 /**
4293 * If any of the given 'sigs' is contained in the existing signatures,
4294 * then add in any new signatures found in 'sigs'. This is used for
4295 * including a new package into an existing shared user id.
4296 */
4297 boolean mergeSignatures(Signature[] sigs, boolean update) {
4298 if (mSignatures == null) {
4299 if (update) {
4300 assignSignatures(sigs);
4301 }
4302 return true;
4303 }
4304 if (sigs == null) {
4305 return false;
4306 }
4307
4308 Signature[] added = null;
4309 int addedCount = 0;
4310 boolean haveMatch = false;
4311 for (int i=0; i<sigs.length; i++) {
4312 Signature sig = sigs[i];
4313 boolean found = false;
4314 for (int j=0; j<mSignatures.length; j++) {
4315 if (mSignatures[j].equals(sig)) {
4316 found = true;
4317 haveMatch = true;
4318 break;
4319 }
4320 }
4321
4322 if (!found) {
4323 if (added == null) {
4324 added = new Signature[sigs.length];
4325 }
4326 added[i] = sig;
4327 addedCount++;
4328 }
4329 }
4330
4331 if (!haveMatch) {
4332 // Nothing matched -- reject the new signatures.
4333 return false;
4334 }
4335 if (added == null) {
4336 // Completely matched -- nothing else to do.
4337 return true;
4338 }
4339
4340 // Add additional signatures in.
4341 if (update) {
4342 Signature[] total = new Signature[addedCount+mSignatures.length];
4343 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
4344 int j = mSignatures.length;
4345 for (int i=0; i<added.length; i++) {
4346 if (added[i] != null) {
4347 total[j] = added[i];
4348 j++;
4349 }
4350 }
4351 mSignatures = total;
4352 }
4353 return true;
4354 }
4355
4356 private void assignSignatures(Signature[] sigs) {
4357 if (sigs == null) {
4358 mSignatures = null;
4359 return;
4360 }
4361 mSignatures = new Signature[sigs.length];
4362 for (int i=0; i<sigs.length; i++) {
4363 mSignatures[i] = sigs[i];
4364 }
4365 }
4366
4367 @Override
4368 public String toString() {
4369 StringBuffer buf = new StringBuffer(128);
4370 buf.append("PackageSignatures{");
4371 buf.append(Integer.toHexString(System.identityHashCode(this)));
4372 buf.append(" [");
4373 if (mSignatures != null) {
4374 for (int i=0; i<mSignatures.length; i++) {
4375 if (i > 0) buf.append(", ");
4376 buf.append(Integer.toHexString(
4377 System.identityHashCode(mSignatures[i])));
4378 }
4379 }
4380 buf.append("]}");
4381 return buf.toString();
4382 }
4383 }
4384
4385 static class PreferredActivity extends IntentFilter {
4386 final int mMatch;
4387 final String[] mSetPackages;
4388 final String[] mSetClasses;
4389 final String[] mSetComponents;
4390 final ComponentName mActivity;
4391 final String mShortActivity;
4392 String mParseError;
4393
4394 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
4395 ComponentName activity) {
4396 super(filter);
4397 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
4398 mActivity = activity;
4399 mShortActivity = activity.flattenToShortString();
4400 mParseError = null;
4401 if (set != null) {
4402 final int N = set.length;
4403 String[] myPackages = new String[N];
4404 String[] myClasses = new String[N];
4405 String[] myComponents = new String[N];
4406 for (int i=0; i<N; i++) {
4407 ComponentName cn = set[i];
4408 if (cn == null) {
4409 mSetPackages = null;
4410 mSetClasses = null;
4411 mSetComponents = null;
4412 return;
4413 }
4414 myPackages[i] = cn.getPackageName().intern();
4415 myClasses[i] = cn.getClassName().intern();
4416 myComponents[i] = cn.flattenToShortString().intern();
4417 }
4418 mSetPackages = myPackages;
4419 mSetClasses = myClasses;
4420 mSetComponents = myComponents;
4421 } else {
4422 mSetPackages = null;
4423 mSetClasses = null;
4424 mSetComponents = null;
4425 }
4426 }
4427
4428 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
4429 IOException {
4430 mShortActivity = parser.getAttributeValue(null, "name");
4431 mActivity = ComponentName.unflattenFromString(mShortActivity);
4432 if (mActivity == null) {
4433 mParseError = "Bad activity name " + mShortActivity;
4434 }
4435 String matchStr = parser.getAttributeValue(null, "match");
4436 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
4437 String setCountStr = parser.getAttributeValue(null, "set");
4438 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
4439
4440 String[] myPackages = setCount > 0 ? new String[setCount] : null;
4441 String[] myClasses = setCount > 0 ? new String[setCount] : null;
4442 String[] myComponents = setCount > 0 ? new String[setCount] : null;
4443
4444 int setPos = 0;
4445
4446 int outerDepth = parser.getDepth();
4447 int type;
4448 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4449 && (type != XmlPullParser.END_TAG
4450 || parser.getDepth() > outerDepth)) {
4451 if (type == XmlPullParser.END_TAG
4452 || type == XmlPullParser.TEXT) {
4453 continue;
4454 }
4455
4456 String tagName = parser.getName();
4457 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
4458 // + parser.getDepth() + " tag=" + tagName);
4459 if (tagName.equals("set")) {
4460 String name = parser.getAttributeValue(null, "name");
4461 if (name == null) {
4462 if (mParseError == null) {
4463 mParseError = "No name in set tag in preferred activity "
4464 + mShortActivity;
4465 }
4466 } else if (setPos >= setCount) {
4467 if (mParseError == null) {
4468 mParseError = "Too many set tags in preferred activity "
4469 + mShortActivity;
4470 }
4471 } else {
4472 ComponentName cn = ComponentName.unflattenFromString(name);
4473 if (cn == null) {
4474 if (mParseError == null) {
4475 mParseError = "Bad set name " + name + " in preferred activity "
4476 + mShortActivity;
4477 }
4478 } else {
4479 myPackages[setPos] = cn.getPackageName();
4480 myClasses[setPos] = cn.getClassName();
4481 myComponents[setPos] = name;
4482 setPos++;
4483 }
4484 }
4485 XmlUtils.skipCurrentTag(parser);
4486 } else if (tagName.equals("filter")) {
4487 //Log.i(TAG, "Starting to parse filter...");
4488 readFromXml(parser);
4489 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
4490 // + parser.getDepth() + " tag=" + parser.getName());
4491 } else {
4492 reportSettingsProblem(Log.WARN,
4493 "Unknown element under <preferred-activities>: "
4494 + parser.getName());
4495 XmlUtils.skipCurrentTag(parser);
4496 }
4497 }
4498
4499 if (setPos != setCount) {
4500 if (mParseError == null) {
4501 mParseError = "Not enough set tags (expected " + setCount
4502 + " but found " + setPos + ") in " + mShortActivity;
4503 }
4504 }
4505
4506 mSetPackages = myPackages;
4507 mSetClasses = myClasses;
4508 mSetComponents = myComponents;
4509 }
4510
4511 public void writeToXml(XmlSerializer serializer) throws IOException {
4512 final int NS = mSetClasses != null ? mSetClasses.length : 0;
4513 serializer.attribute(null, "name", mShortActivity);
4514 serializer.attribute(null, "match", Integer.toHexString(mMatch));
4515 serializer.attribute(null, "set", Integer.toString(NS));
4516 for (int s=0; s<NS; s++) {
4517 serializer.startTag(null, "set");
4518 serializer.attribute(null, "name", mSetComponents[s]);
4519 serializer.endTag(null, "set");
4520 }
4521 serializer.startTag(null, "filter");
4522 super.writeToXml(serializer);
4523 serializer.endTag(null, "filter");
4524 }
4525
4526 boolean sameSet(List<ResolveInfo> query, int priority) {
4527 if (mSetPackages == null) return false;
4528 final int NQ = query.size();
4529 final int NS = mSetPackages.length;
4530 int numMatch = 0;
4531 for (int i=0; i<NQ; i++) {
4532 ResolveInfo ri = query.get(i);
4533 if (ri.priority != priority) continue;
4534 ActivityInfo ai = ri.activityInfo;
4535 boolean good = false;
4536 for (int j=0; j<NS; j++) {
4537 if (mSetPackages[j].equals(ai.packageName)
4538 && mSetClasses[j].equals(ai.name)) {
4539 numMatch++;
4540 good = true;
4541 break;
4542 }
4543 }
4544 if (!good) return false;
4545 }
4546 return numMatch == NS;
4547 }
4548 }
4549
4550 static class GrantedPermissions {
4551 final int pkgFlags;
4552
4553 HashSet<String> grantedPermissions = new HashSet<String>();
4554 int[] gids;
4555
4556 HashSet<String> loadedPermissions = new HashSet<String>();
4557
4558 GrantedPermissions(int pkgFlags) {
4559 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
4560 }
4561 }
4562
4563 /**
4564 * Settings base class for pending and resolved classes.
4565 */
4566 static class PackageSettingBase extends GrantedPermissions {
4567 final String name;
4568 final File codePath;
4569 final String codePathString;
4570 final File resourcePath;
4571 final String resourcePathString;
4572 long timeStamp;
4573 String timeStampString = "0";
4574
4575 PackageSignatures signatures = new PackageSignatures();
4576
4577 boolean permissionsFixed;
4578
4579 /* Explicitly disabled components */
4580 HashSet<String> disabledComponents = new HashSet<String>(0);
4581 /* Explicitly enabled components */
4582 HashSet<String> enabledComponents = new HashSet<String>(0);
4583 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
4584 int installStatus = PKG_INSTALL_COMPLETE;
4585
4586 PackageSettingBase(String name, File codePath, File resourcePath,
4587 int pkgFlags) {
4588 super(pkgFlags);
4589 this.name = name;
4590 this.codePath = codePath;
4591 this.codePathString = codePath.toString();
4592 this.resourcePath = resourcePath;
4593 this.resourcePathString = resourcePath.toString();
4594 }
4595
4596 public void setInstallStatus(int newStatus) {
4597 installStatus = newStatus;
4598 }
4599
4600 public int getInstallStatus() {
4601 return installStatus;
4602 }
4603
4604 public void setTimeStamp(long newStamp) {
4605 if (newStamp != timeStamp) {
4606 timeStamp = newStamp;
4607 timeStampString = Long.toString(newStamp);
4608 }
4609 }
4610
4611 public void setTimeStamp(long newStamp, String newStampStr) {
4612 timeStamp = newStamp;
4613 timeStampString = newStampStr;
4614 }
4615
4616 public void copyFrom(PackageSettingBase base) {
4617 grantedPermissions = base.grantedPermissions;
4618 gids = base.gids;
4619 loadedPermissions = base.loadedPermissions;
4620
4621 timeStamp = base.timeStamp;
4622 timeStampString = base.timeStampString;
4623 signatures = base.signatures;
4624 permissionsFixed = base.permissionsFixed;
4625 disabledComponents = base.disabledComponents;
4626 enabledComponents = base.enabledComponents;
4627 enabled = base.enabled;
4628 installStatus = base.installStatus;
4629 }
4630
4631 void enableComponentLP(String componentClassName) {
4632 disabledComponents.remove(componentClassName);
4633 enabledComponents.add(componentClassName);
4634 }
4635
4636 void disableComponentLP(String componentClassName) {
4637 enabledComponents.remove(componentClassName);
4638 disabledComponents.add(componentClassName);
4639 }
4640
4641 void restoreComponentLP(String componentClassName) {
4642 enabledComponents.remove(componentClassName);
4643 disabledComponents.remove(componentClassName);
4644 }
4645
4646 int currentEnabledStateLP(String componentName) {
4647 if (enabledComponents.contains(componentName)) {
4648 return COMPONENT_ENABLED_STATE_ENABLED;
4649 } else if (disabledComponents.contains(componentName)) {
4650 return COMPONENT_ENABLED_STATE_DISABLED;
4651 } else {
4652 return COMPONENT_ENABLED_STATE_DEFAULT;
4653 }
4654 }
4655 }
4656
4657 /**
4658 * Settings data for a particular package we know about.
4659 */
4660 static final class PackageSetting extends PackageSettingBase {
4661 int userId;
4662 PackageParser.Package pkg;
4663 SharedUserSetting sharedUser;
4664
4665 PackageSetting(String name, File codePath, File resourcePath,
4666 int pkgFlags) {
4667 super(name, codePath, resourcePath, pkgFlags);
4668 }
4669
4670 @Override
4671 public String toString() {
4672 return "PackageSetting{"
4673 + Integer.toHexString(System.identityHashCode(this))
4674 + " " + name + "/" + userId + "}";
4675 }
4676 }
4677
4678 /**
4679 * Settings data for a particular shared user ID we know about.
4680 */
4681 static final class SharedUserSetting extends GrantedPermissions {
4682 final String name;
4683 int userId;
4684 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
4685 final PackageSignatures signatures = new PackageSignatures();
4686
4687 SharedUserSetting(String _name, int _pkgFlags) {
4688 super(_pkgFlags);
4689 name = _name;
4690 }
4691
4692 @Override
4693 public String toString() {
4694 return "SharedUserSetting{"
4695 + Integer.toHexString(System.identityHashCode(this))
4696 + " " + name + "/" + userId + "}";
4697 }
4698 }
4699
4700 /**
4701 * Holds information about dynamic settings.
4702 */
4703 private static final class Settings {
4704 private final File mSettingsFilename;
4705 private final File mBackupSettingsFilename;
4706 private final HashMap<String, PackageSetting> mPackages =
4707 new HashMap<String, PackageSetting>();
4708 // The user's preferred packages/applications, in order of preference.
4709 // First is the most preferred.
4710 private final ArrayList<PackageSetting> mPreferredPackages =
4711 new ArrayList<PackageSetting>();
4712 // The user's preferred activities associated with particular intent
4713 // filters.
4714 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
4715 new IntentResolver<PreferredActivity, PreferredActivity>() {
4716 @Override
4717 protected void dumpFilter(Printer out, String prefix,
4718 PreferredActivity filter) {
4719 out.println(prefix
4720 + Integer.toHexString(System.identityHashCode(filter))
4721 + " " + filter.mActivity.flattenToShortString()
4722 + " match=0x" + Integer.toHexString(filter.mMatch));
4723 if (filter.mSetComponents != null) {
4724 out.println(prefix + " Selected from:");
4725 for (int i=0; i<filter.mSetComponents.length; i++) {
4726 out.println(prefix + " " + filter.mSetComponents[i]);
4727 }
4728 }
4729 }
4730 };
4731 private final HashMap<String, SharedUserSetting> mSharedUsers =
4732 new HashMap<String, SharedUserSetting>();
4733 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
4734 private final SparseArray<Object> mOtherUserIds =
4735 new SparseArray<Object>();
4736
4737 // For reading/writing settings file.
4738 private final ArrayList<Signature> mPastSignatures =
4739 new ArrayList<Signature>();
4740
4741 // Mapping from permission names to info about them.
4742 final HashMap<String, BasePermission> mPermissions =
4743 new HashMap<String, BasePermission>();
4744
4745 // Mapping from permission tree names to info about them.
4746 final HashMap<String, BasePermission> mPermissionTrees =
4747 new HashMap<String, BasePermission>();
4748
4749 private final ArrayList<String> mPendingPreferredPackages
4750 = new ArrayList<String>();
4751
4752 private final StringBuilder mReadMessages = new StringBuilder();
4753
4754 private static final class PendingPackage extends PackageSettingBase {
4755 final int sharedId;
4756
4757 PendingPackage(String name, File codePath, File resourcePath,
4758 int sharedId, int pkgFlags) {
4759 super(name, codePath, resourcePath, pkgFlags);
4760 this.sharedId = sharedId;
4761 }
4762 }
4763 private final ArrayList<PendingPackage> mPendingPackages
4764 = new ArrayList<PendingPackage>();
4765
4766 Settings() {
4767 File dataDir = Environment.getDataDirectory();
4768 File systemDir = new File(dataDir, "system");
4769 systemDir.mkdirs();
4770 FileUtils.setPermissions(systemDir.toString(),
4771 FileUtils.S_IRWXU|FileUtils.S_IRWXG
4772 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
4773 -1, -1);
4774 mSettingsFilename = new File(systemDir, "packages.xml");
4775 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
4776 }
4777
4778 PackageSetting getPackageLP(PackageParser.Package pkg,
4779 SharedUserSetting sharedUser, File codePath, File resourcePath,
4780 int pkgFlags, boolean create) {
4781 final String name = pkg.packageName;
4782 PackageSetting p = getPackageLP(name, sharedUser, codePath,
4783 resourcePath, pkgFlags, create);
4784 if (p != null) {
4785 p.pkg = pkg;
4786 }
4787 return p;
4788 }
4789
4790 PackageSetting peekPackageLP(String name, String codePath) {
4791 PackageSetting p = mPackages.get(name);
4792 if (p != null && p.codePath.getPath().equals(codePath)) {
4793 return p;
4794 }
4795 return null;
4796 }
4797
4798 void setInstallStatus(String pkgName, int status) {
4799 PackageSetting p = mPackages.get(pkgName);
4800 if(p != null) {
4801 if(p.getInstallStatus() != status) {
4802 p.setInstallStatus(status);
4803 }
4804 }
4805 }
4806
4807 int getInstallStatus(String pkgName) {
4808 PackageSetting p = mPackages.get(pkgName);
4809 if(p != null) {
4810 return p.getInstallStatus();
4811 }
4812 return -1;
4813 }
4814
4815 SharedUserSetting getSharedUserLP(String name,
4816 int pkgFlags, boolean create) {
4817 SharedUserSetting s = mSharedUsers.get(name);
4818 if (s == null) {
4819 if (!create) {
4820 return null;
4821 }
4822 s = new SharedUserSetting(name, pkgFlags);
4823 if (MULTIPLE_APPLICATION_UIDS) {
4824 s.userId = newUserIdLP(s);
4825 } else {
4826 s.userId = FIRST_APPLICATION_UID;
4827 }
4828 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
4829 // < 0 means we couldn't assign a userid; fall out and return
4830 // s, which is currently null
4831 if (s.userId >= 0) {
4832 mSharedUsers.put(name, s);
4833 }
4834 }
4835
4836 return s;
4837 }
4838
4839 PackageSetting addPackageLP(String name, File codePath,
4840 File resourcePath, int uid, int pkgFlags) {
4841 PackageSetting p = mPackages.get(name);
4842 if (p != null) {
4843 if (p.userId == uid) {
4844 return p;
4845 }
4846 reportSettingsProblem(Log.ERROR,
4847 "Adding duplicate package, keeping first: " + name);
4848 return null;
4849 }
4850 p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
4851 p.userId = uid;
4852 if (addUserIdLP(uid, p, name)) {
4853 mPackages.put(name, p);
4854 return p;
4855 }
4856 return null;
4857 }
4858
4859 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
4860 SharedUserSetting s = mSharedUsers.get(name);
4861 if (s != null) {
4862 if (s.userId == uid) {
4863 return s;
4864 }
4865 reportSettingsProblem(Log.ERROR,
4866 "Adding duplicate shared user, keeping first: " + name);
4867 return null;
4868 }
4869 s = new SharedUserSetting(name, pkgFlags);
4870 s.userId = uid;
4871 if (addUserIdLP(uid, s, name)) {
4872 mSharedUsers.put(name, s);
4873 return s;
4874 }
4875 return null;
4876 }
4877
4878 private PackageSetting getPackageLP(String name,
4879 SharedUserSetting sharedUser, File codePath, File resourcePath,
4880 int pkgFlags, boolean create) {
4881 PackageSetting p = mPackages.get(name);
4882 if (p != null) {
4883 if (!p.codePath.equals(codePath)) {
4884 reportSettingsProblem(Log.WARN,
4885 "Package " + name + " codePath changed from " + p.codePath
4886 + " to " + codePath + "; replacing with new");
4887 p = null;
4888 } else if (p.sharedUser != sharedUser) {
4889 reportSettingsProblem(Log.WARN,
4890 "Package " + name + " shared user changed from "
4891 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
4892 + " to "
4893 + (sharedUser != null ? sharedUser.name : "<nothing>")
4894 + "; replacing with new");
4895 p = null;
4896 }
4897 }
4898 if (p == null) {
4899 if (!create) {
4900 return null;
4901 }
4902 p = new PackageSetting(name, codePath, resourcePath, pkgFlags);
4903 if (sharedUser != null) {
4904 p.userId = sharedUser.userId;
4905 } else if (MULTIPLE_APPLICATION_UIDS) {
4906 p.userId = newUserIdLP(p);
4907 } else {
4908 p.userId = FIRST_APPLICATION_UID;
4909 }
4910
4911 if (p.userId < 0) {
4912 reportSettingsProblem(Log.WARN,
4913 "Package " + name + " could not be assigned a valid uid");
4914 return null;
4915 }
4916 mPackages.put(name, p);
4917 }
4918
4919 if (sharedUser != null) {
4920 if (p.sharedUser != null && p.sharedUser != sharedUser) {
4921 reportSettingsProblem(Log.ERROR,
4922 "Package " + p.name + " was user "
4923 + p.sharedUser + " but is now " + sharedUser
4924 + "; I am not changing its files so it will probably fail!");
4925 p.sharedUser.packages.remove(p);
4926 } else if (p.userId != sharedUser.userId) {
4927 reportSettingsProblem(Log.ERROR,
4928 "Package " + p.name + " was user id " + p.userId
4929 + " but is now user " + sharedUser
4930 + " with id " + sharedUser.userId
4931 + "; I am not changing its files so it will probably fail!");
4932 }
4933
4934 sharedUser.packages.add(p);
4935 p.sharedUser = sharedUser;
4936 p.userId = sharedUser.userId;
4937 }
4938
4939 return p;
4940 }
4941
4942 private int removePackageLP(String name) {
4943 PackageSetting p = mPackages.get(name);
4944 if (p != null) {
4945 mPackages.remove(name);
4946 if (p.sharedUser != null) {
4947 p.sharedUser.packages.remove(p);
4948 if (p.sharedUser.packages.size() == 0) {
4949 mSharedUsers.remove(p.sharedUser.name);
4950 removeUserIdLP(p.sharedUser.userId);
4951 return p.sharedUser.userId;
4952 }
4953 } else {
4954 removeUserIdLP(p.userId);
4955 return p.userId;
4956 }
4957 }
4958 return -1;
4959 }
4960
4961 private boolean addUserIdLP(int uid, Object obj, Object name) {
4962 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
4963 return false;
4964 }
4965
4966 if (uid >= FIRST_APPLICATION_UID) {
4967 int N = mUserIds.size();
4968 final int index = uid - FIRST_APPLICATION_UID;
4969 while (index >= N) {
4970 mUserIds.add(null);
4971 N++;
4972 }
4973 if (mUserIds.get(index) != null) {
4974 reportSettingsProblem(Log.ERROR,
4975 "Adding duplicate shared id: " + uid
4976 + " name=" + name);
4977 return false;
4978 }
4979 mUserIds.set(index, obj);
4980 } else {
4981 if (mOtherUserIds.get(uid) != null) {
4982 reportSettingsProblem(Log.ERROR,
4983 "Adding duplicate shared id: " + uid
4984 + " name=" + name);
4985 return false;
4986 }
4987 mOtherUserIds.put(uid, obj);
4988 }
4989 return true;
4990 }
4991
4992 public Object getUserIdLP(int uid) {
4993 if (uid >= FIRST_APPLICATION_UID) {
4994 int N = mUserIds.size();
4995 final int index = uid - FIRST_APPLICATION_UID;
4996 return index < N ? mUserIds.get(index) : null;
4997 } else {
4998 return mOtherUserIds.get(uid);
4999 }
5000 }
5001
5002 private void removeUserIdLP(int uid) {
5003 if (uid >= FIRST_APPLICATION_UID) {
5004 int N = mUserIds.size();
5005 final int index = uid - FIRST_APPLICATION_UID;
5006 if (index < N) mUserIds.set(index, null);
5007 } else {
5008 mOtherUserIds.remove(uid);
5009 }
5010 }
5011
5012 void writeLP() {
5013 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
5014
5015 // Keep the old settings around until we know the new ones have
5016 // been successfully written.
5017 if (mSettingsFilename.exists()) {
5018 if (mBackupSettingsFilename.exists()) {
5019 mBackupSettingsFilename.delete();
5020 }
5021 mSettingsFilename.renameTo(mBackupSettingsFilename);
5022 }
5023
5024 mPastSignatures.clear();
5025
5026 try {
5027 FileOutputStream str = new FileOutputStream(mSettingsFilename);
5028
5029 //XmlSerializer serializer = XmlUtils.serializerInstance();
5030 XmlSerializer serializer = new FastXmlSerializer();
5031 serializer.setOutput(str, "utf-8");
5032 serializer.startDocument(null, true);
5033 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
5034
5035 serializer.startTag(null, "packages");
5036
5037 serializer.startTag(null, "permission-trees");
5038 for (BasePermission bp : mPermissionTrees.values()) {
5039 writePermission(serializer, bp);
5040 }
5041 serializer.endTag(null, "permission-trees");
5042
5043 serializer.startTag(null, "permissions");
5044 for (BasePermission bp : mPermissions.values()) {
5045 writePermission(serializer, bp);
5046 }
5047 serializer.endTag(null, "permissions");
5048
5049 for (PackageSetting pkg : mPackages.values()) {
5050 serializer.startTag(null, "package");
5051 serializer.attribute(null, "name", pkg.name);
5052 serializer.attribute(null, "codePath", pkg.codePathString);
5053 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
5054 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
5055 }
5056 serializer.attribute(null, "system",
5057 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
5058 ? "true" : "false");
5059 serializer.attribute(null, "ts", pkg.timeStampString);
5060 if (pkg.sharedUser == null) {
5061 serializer.attribute(null, "userId",
5062 Integer.toString(pkg.userId));
5063 } else {
5064 serializer.attribute(null, "sharedUserId",
5065 Integer.toString(pkg.userId));
5066 }
5067 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
5068 serializer.attribute(null, "enabled",
5069 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
5070 ? "true" : "false");
5071 }
5072 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
5073 serializer.attribute(null, "installStatus", "false");
5074 }
5075 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
5076 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5077 serializer.startTag(null, "perms");
5078 if (pkg.sharedUser == null) {
5079 // If this is a shared user, the permissions will
5080 // be written there. We still need to write an
5081 // empty permissions list so permissionsFixed will
5082 // be set.
5083 for (String name : pkg.grantedPermissions) {
5084 serializer.startTag(null, "item");
5085 serializer.attribute(null, "name", name);
5086 serializer.endTag(null, "item");
5087 }
5088 }
5089 serializer.endTag(null, "perms");
5090 }
5091 if (pkg.disabledComponents.size() > 0) {
5092 serializer.startTag(null, "disabled-components");
5093 for (String name : pkg.disabledComponents) {
5094 serializer.startTag(null, "item");
5095 serializer.attribute(null, "name", name);
5096 serializer.endTag(null, "item");
5097 }
5098 serializer.endTag(null, "disabled-components");
5099 }
5100 if (pkg.enabledComponents.size() > 0) {
5101 serializer.startTag(null, "enabled-components");
5102 for (String name : pkg.enabledComponents) {
5103 serializer.startTag(null, "item");
5104 serializer.attribute(null, "name", name);
5105 serializer.endTag(null, "item");
5106 }
5107 serializer.endTag(null, "enabled-components");
5108 }
5109 serializer.endTag(null, "package");
5110 }
5111
5112 serializer.startTag(null, "preferred-packages");
5113 int N = mPreferredPackages.size();
5114 for (int i=0; i<N; i++) {
5115 PackageSetting pkg = mPreferredPackages.get(i);
5116 serializer.startTag(null, "item");
5117 serializer.attribute(null, "name", pkg.name);
5118 serializer.endTag(null, "item");
5119 }
5120 serializer.endTag(null, "preferred-packages");
5121
5122 serializer.startTag(null, "preferred-activities");
5123 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
5124 serializer.startTag(null, "item");
5125 pa.writeToXml(serializer);
5126 serializer.endTag(null, "item");
5127 }
5128 serializer.endTag(null, "preferred-activities");
5129
5130 for (SharedUserSetting usr : mSharedUsers.values()) {
5131 serializer.startTag(null, "shared-user");
5132 serializer.attribute(null, "name", usr.name);
5133 serializer.attribute(null, "userId",
5134 Integer.toString(usr.userId));
5135 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
5136 serializer.startTag(null, "perms");
5137 for (String name : usr.grantedPermissions) {
5138 serializer.startTag(null, "item");
5139 serializer.attribute(null, "name", name);
5140 serializer.endTag(null, "item");
5141 }
5142 serializer.endTag(null, "perms");
5143 serializer.endTag(null, "shared-user");
5144 }
5145
5146 serializer.endTag(null, "packages");
5147
5148 serializer.endDocument();
5149
5150 str.flush();
5151 str.close();
5152
5153 // New settings successfully written, old ones are no longer
5154 // needed.
5155 mBackupSettingsFilename.delete();
5156 FileUtils.setPermissions(mSettingsFilename.toString(),
5157 FileUtils.S_IRUSR|FileUtils.S_IWUSR
5158 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
5159 |FileUtils.S_IROTH,
5160 -1, -1);
5161
5162 } catch(XmlPullParserException e) {
5163 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5164
5165 } catch(java.io.IOException e) {
5166 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
5167
5168 }
5169
5170 //Debug.stopMethodTracing();
5171 }
5172
5173 void writePermission(XmlSerializer serializer, BasePermission bp)
5174 throws XmlPullParserException, java.io.IOException {
5175 if (bp.type != BasePermission.TYPE_BUILTIN
5176 && bp.sourcePackage != null) {
5177 serializer.startTag(null, "item");
5178 serializer.attribute(null, "name", bp.name);
5179 serializer.attribute(null, "package", bp.sourcePackage);
5180 if (DEBUG_SETTINGS) Log.v(TAG,
5181 "Writing perm: name=" + bp.name + " type=" + bp.type);
5182 if (bp.type == BasePermission.TYPE_DYNAMIC) {
5183 PermissionInfo pi = bp.perm != null ? bp.perm.info
5184 : bp.pendingInfo;
5185 if (pi != null) {
5186 serializer.attribute(null, "type", "dynamic");
5187 if (pi.icon != 0) {
5188 serializer.attribute(null, "icon",
5189 Integer.toString(pi.icon));
5190 }
5191 if (pi.nonLocalizedLabel != null) {
5192 serializer.attribute(null, "label",
5193 pi.nonLocalizedLabel.toString());
5194 }
5195 if (pi.protectionLevel !=
5196 PermissionInfo.PROTECTION_NORMAL) {
5197 serializer.attribute(null, "protection",
5198 Integer.toString(pi.protectionLevel));
5199 }
5200 }
5201 }
5202 serializer.endTag(null, "item");
5203 }
5204 }
5205
5206 String getReadMessagesLP() {
5207 return mReadMessages.toString();
5208 }
5209
5210 ArrayList<String> getListOfIncompleteInstallPackages() {
5211 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
5212 Iterator<String> its = kList.iterator();
5213 ArrayList<String> ret = new ArrayList<String>();
5214 while(its.hasNext()) {
5215 String key = its.next();
5216 PackageSetting ps = mPackages.get(key);
5217 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
5218 ret.add(key);
5219 }
5220 }
5221 return ret;
5222 }
5223
5224 boolean readLP() {
5225 FileInputStream str = null;
5226 if (mBackupSettingsFilename.exists()) {
5227 try {
5228 str = new FileInputStream(mBackupSettingsFilename);
5229 mReadMessages.append("Reading from backup settings file\n");
5230 Log.i(TAG, "Reading from backup settings file!");
5231 } catch (java.io.IOException e) {
5232 // We'll try for the normal settings file.
5233 }
5234 }
5235
5236 mPastSignatures.clear();
5237
5238 try {
5239 if (str == null) {
5240 if (!mSettingsFilename.exists()) {
5241 mReadMessages.append("No settings file found\n");
5242 Log.i(TAG, "No current settings file!");
5243 return false;
5244 }
5245 str = new FileInputStream(mSettingsFilename);
5246 }
5247 XmlPullParser parser = Xml.newPullParser();
5248 parser.setInput(str, null);
5249
5250 int type;
5251 while ((type=parser.next()) != XmlPullParser.START_TAG
5252 && type != XmlPullParser.END_DOCUMENT) {
5253 ;
5254 }
5255
5256 if (type != XmlPullParser.START_TAG) {
5257 mReadMessages.append("No start tag found in settings file\n");
5258 Log.e(TAG, "No start tag found in package manager settings");
5259 return false;
5260 }
5261
5262 int outerDepth = parser.getDepth();
5263 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5264 && (type != XmlPullParser.END_TAG
5265 || parser.getDepth() > outerDepth)) {
5266 if (type == XmlPullParser.END_TAG
5267 || type == XmlPullParser.TEXT) {
5268 continue;
5269 }
5270
5271 String tagName = parser.getName();
5272 if (tagName.equals("package")) {
5273 readPackageLP(parser);
5274 } else if (tagName.equals("permissions")) {
5275 readPermissionsLP(mPermissions, parser);
5276 } else if (tagName.equals("permission-trees")) {
5277 readPermissionsLP(mPermissionTrees, parser);
5278 } else if (tagName.equals("shared-user")) {
5279 readSharedUserLP(parser);
5280 } else if (tagName.equals("preferred-packages")) {
5281 readPreferredPackagesLP(parser);
5282 } else if (tagName.equals("preferred-activities")) {
5283 readPreferredActivitiesLP(parser);
5284 } else {
5285 Log.w(TAG, "Unknown element under <packages>: "
5286 + parser.getName());
5287 XmlUtils.skipCurrentTag(parser);
5288 }
5289 }
5290
5291 str.close();
5292
5293 } catch(XmlPullParserException e) {
5294 mReadMessages.append("Error reading: " + e.toString());
5295 Log.e(TAG, "Error reading package manager settings", e);
5296
5297 } catch(java.io.IOException e) {
5298 mReadMessages.append("Error reading: " + e.toString());
5299 Log.e(TAG, "Error reading package manager settings", e);
5300
5301 }
5302
5303 int N = mPendingPackages.size();
5304 for (int i=0; i<N; i++) {
5305 final PendingPackage pp = mPendingPackages.get(i);
5306 Object idObj = getUserIdLP(pp.sharedId);
5307 if (idObj != null && idObj instanceof SharedUserSetting) {
5308 PackageSetting p = getPackageLP(pp.name,
5309 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
5310 pp.pkgFlags, true);
5311 if (p == null) {
5312 Log.w(TAG, "Unable to create application package for "
5313 + pp.name);
5314 continue;
5315 }
5316 p.copyFrom(pp);
5317 } else if (idObj != null) {
5318 String msg = "Bad package setting: package " + pp.name
5319 + " has shared uid " + pp.sharedId
5320 + " that is not a shared uid\n";
5321 mReadMessages.append(msg);
5322 Log.e(TAG, msg);
5323 } else {
5324 String msg = "Bad package setting: package " + pp.name
5325 + " has shared uid " + pp.sharedId
5326 + " that is not defined\n";
5327 mReadMessages.append(msg);
5328 Log.e(TAG, msg);
5329 }
5330 }
5331 mPendingPackages.clear();
5332
5333 N = mPendingPreferredPackages.size();
5334 mPreferredPackages.clear();
5335 for (int i=0; i<N; i++) {
5336 final String name = mPendingPreferredPackages.get(i);
5337 final PackageSetting p = mPackages.get(name);
5338 if (p != null) {
5339 mPreferredPackages.add(p);
5340 } else {
5341 Log.w(TAG, "Unknown preferred package: " + name);
5342 }
5343 }
5344 mPendingPreferredPackages.clear();
5345
5346 mReadMessages.append("Read completed successfully: "
5347 + mPackages.size() + " packages, "
5348 + mSharedUsers.size() + " shared uids\n");
5349
5350 return true;
5351 }
5352
5353 private int readInt(XmlPullParser parser, String ns, String name,
5354 int defValue) {
5355 String v = parser.getAttributeValue(ns, name);
5356 try {
5357 if (v == null) {
5358 return defValue;
5359 }
5360 return Integer.parseInt(v);
5361 } catch (NumberFormatException e) {
5362 reportSettingsProblem(Log.WARN,
5363 "Error in package manager settings: attribute " +
5364 name + " has bad integer value " + v + " at "
5365 + parser.getPositionDescription());
5366 }
5367 return defValue;
5368 }
5369
5370 private void readPermissionsLP(HashMap<String, BasePermission> out,
5371 XmlPullParser parser)
5372 throws IOException, XmlPullParserException {
5373 int outerDepth = parser.getDepth();
5374 int type;
5375 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5376 && (type != XmlPullParser.END_TAG
5377 || parser.getDepth() > outerDepth)) {
5378 if (type == XmlPullParser.END_TAG
5379 || type == XmlPullParser.TEXT) {
5380 continue;
5381 }
5382
5383 String tagName = parser.getName();
5384 if (tagName.equals("item")) {
5385 String name = parser.getAttributeValue(null, "name");
5386 String sourcePackage = parser.getAttributeValue(null, "package");
5387 String ptype = parser.getAttributeValue(null, "type");
5388 if (name != null && sourcePackage != null) {
5389 boolean dynamic = "dynamic".equals(ptype);
5390 BasePermission bp = new BasePermission(name, sourcePackage,
5391 dynamic
5392 ? BasePermission.TYPE_DYNAMIC
5393 : BasePermission.TYPE_NORMAL);
5394 if (dynamic) {
5395 PermissionInfo pi = new PermissionInfo();
5396 pi.packageName = sourcePackage.intern();
5397 pi.name = name.intern();
5398 pi.icon = readInt(parser, null, "icon", 0);
5399 pi.nonLocalizedLabel = parser.getAttributeValue(
5400 null, "label");
5401 pi.protectionLevel = readInt(parser, null, "protection",
5402 PermissionInfo.PROTECTION_NORMAL);
5403 bp.pendingInfo = pi;
5404 }
5405 out.put(bp.name, bp);
5406 } else {
5407 reportSettingsProblem(Log.WARN,
5408 "Error in package manager settings: permissions has"
5409 + " no name at " + parser.getPositionDescription());
5410 }
5411 } else {
5412 reportSettingsProblem(Log.WARN,
5413 "Unknown element reading permissions: "
5414 + parser.getName() + " at "
5415 + parser.getPositionDescription());
5416 }
5417 XmlUtils.skipCurrentTag(parser);
5418 }
5419 }
5420
5421 private void readPackageLP(XmlPullParser parser)
5422 throws XmlPullParserException, IOException {
5423 String name = null;
5424 String idStr = null;
5425 String sharedIdStr = null;
5426 String codePathStr = null;
5427 String resourcePathStr = null;
5428 String systemStr = null;
5429 int pkgFlags = 0;
5430 String timeStampStr;
5431 long timeStamp = 0;
5432 PackageSettingBase packageSetting = null;
5433 try {
5434 name = parser.getAttributeValue(null, "name");
5435 idStr = parser.getAttributeValue(null, "userId");
5436 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
5437 codePathStr = parser.getAttributeValue(null, "codePath");
5438 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
5439 systemStr = parser.getAttributeValue(null, "system");
5440 if (systemStr != null) {
5441 if ("true".equals(systemStr)) {
5442 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
5443 }
5444 } else {
5445 // Old settings that don't specify system... just treat
5446 // them as system, good enough.
5447 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
5448 }
5449 timeStampStr = parser.getAttributeValue(null, "ts");
5450 if (timeStampStr != null) {
5451 try {
5452 timeStamp = Long.parseLong(timeStampStr);
5453 } catch (NumberFormatException e) {
5454 }
5455 }
5456 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
5457 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
5458 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
5459 if (resourcePathStr == null) {
5460 resourcePathStr = codePathStr;
5461 }
5462 if (name == null) {
5463 reportSettingsProblem(Log.WARN,
5464 "Error in package manager settings: <package> has no name at "
5465 + parser.getPositionDescription());
5466 } else if (codePathStr == null) {
5467 reportSettingsProblem(Log.WARN,
5468 "Error in package manager settings: <package> has no codePath at "
5469 + parser.getPositionDescription());
5470 } else if (userId > 0) {
5471 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
5472 new File(resourcePathStr), userId, pkgFlags);
5473 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
5474 + ": userId=" + userId + " pkg=" + packageSetting);
5475 if (packageSetting == null) {
5476 reportSettingsProblem(Log.ERROR,
5477 "Failure adding uid " + userId
5478 + " while parsing settings at "
5479 + parser.getPositionDescription());
5480 } else {
5481 packageSetting.setTimeStamp(timeStamp, timeStampStr);
5482 }
5483 } else if (sharedIdStr != null) {
5484 userId = sharedIdStr != null
5485 ? Integer.parseInt(sharedIdStr) : 0;
5486 if (userId > 0) {
5487 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
5488 new File(resourcePathStr), userId, pkgFlags);
5489 packageSetting.setTimeStamp(timeStamp, timeStampStr);
5490 mPendingPackages.add((PendingPackage) packageSetting);
5491 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
5492 + ": sharedUserId=" + userId + " pkg="
5493 + packageSetting);
5494 } else {
5495 reportSettingsProblem(Log.WARN,
5496 "Error in package manager settings: package "
5497 + name + " has bad sharedId " + sharedIdStr
5498 + " at " + parser.getPositionDescription());
5499 }
5500 } else {
5501 reportSettingsProblem(Log.WARN,
5502 "Error in package manager settings: package "
5503 + name + " has bad userId " + idStr + " at "
5504 + parser.getPositionDescription());
5505 }
5506 } catch (NumberFormatException e) {
5507 reportSettingsProblem(Log.WARN,
5508 "Error in package manager settings: package "
5509 + name + " has bad userId " + idStr + " at "
5510 + parser.getPositionDescription());
5511 }
5512 if (packageSetting != null) {
5513 final String enabledStr = parser.getAttributeValue(null, "enabled");
5514 if (enabledStr != null) {
5515 if (enabledStr.equalsIgnoreCase("true")) {
5516 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
5517 } else if (enabledStr.equalsIgnoreCase("false")) {
5518 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
5519 } else if (enabledStr.equalsIgnoreCase("default")) {
5520 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5521 } else {
5522 reportSettingsProblem(Log.WARN,
5523 "Error in package manager settings: package "
5524 + name + " has bad enabled value: " + idStr
5525 + " at " + parser.getPositionDescription());
5526 }
5527 } else {
5528 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5529 }
5530 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
5531 if (installStatusStr != null) {
5532 if (installStatusStr.equalsIgnoreCase("false")) {
5533 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
5534 } else {
5535 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
5536 }
5537 }
5538
5539 int outerDepth = parser.getDepth();
5540 int type;
5541 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5542 && (type != XmlPullParser.END_TAG
5543 || parser.getDepth() > outerDepth)) {
5544 if (type == XmlPullParser.END_TAG
5545 || type == XmlPullParser.TEXT) {
5546 continue;
5547 }
5548
5549 String tagName = parser.getName();
5550 if (tagName.equals("disabled-components")) {
5551 readDisabledComponentsLP(packageSetting, parser);
5552 } else if (tagName.equals("enabled-components")) {
5553 readEnabledComponentsLP(packageSetting, parser);
5554 } else if (tagName.equals("sigs")) {
5555 packageSetting.signatures.readXml(parser, mPastSignatures);
5556 } else if (tagName.equals("perms")) {
5557 readGrantedPermissionsLP(parser,
5558 packageSetting.loadedPermissions);
5559 packageSetting.permissionsFixed = true;
5560 } else {
5561 reportSettingsProblem(Log.WARN,
5562 "Unknown element under <package>: "
5563 + parser.getName());
5564 XmlUtils.skipCurrentTag(parser);
5565 }
5566 }
5567 } else {
5568 XmlUtils.skipCurrentTag(parser);
5569 }
5570 }
5571
5572 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
5573 XmlPullParser parser)
5574 throws IOException, XmlPullParserException {
5575 int outerDepth = parser.getDepth();
5576 int type;
5577 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5578 && (type != XmlPullParser.END_TAG
5579 || parser.getDepth() > outerDepth)) {
5580 if (type == XmlPullParser.END_TAG
5581 || type == XmlPullParser.TEXT) {
5582 continue;
5583 }
5584
5585 String tagName = parser.getName();
5586 if (tagName.equals("item")) {
5587 String name = parser.getAttributeValue(null, "name");
5588 if (name != null) {
5589 packageSetting.disabledComponents.add(name.intern());
5590 } else {
5591 reportSettingsProblem(Log.WARN,
5592 "Error in package manager settings: <disabled-components> has"
5593 + " no name at " + parser.getPositionDescription());
5594 }
5595 } else {
5596 reportSettingsProblem(Log.WARN,
5597 "Unknown element under <disabled-components>: "
5598 + parser.getName());
5599 }
5600 XmlUtils.skipCurrentTag(parser);
5601 }
5602 }
5603
5604 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
5605 XmlPullParser parser)
5606 throws IOException, XmlPullParserException {
5607 int outerDepth = parser.getDepth();
5608 int type;
5609 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5610 && (type != XmlPullParser.END_TAG
5611 || parser.getDepth() > outerDepth)) {
5612 if (type == XmlPullParser.END_TAG
5613 || type == XmlPullParser.TEXT) {
5614 continue;
5615 }
5616
5617 String tagName = parser.getName();
5618 if (tagName.equals("item")) {
5619 String name = parser.getAttributeValue(null, "name");
5620 if (name != null) {
5621 packageSetting.enabledComponents.add(name.intern());
5622 } else {
5623 reportSettingsProblem(Log.WARN,
5624 "Error in package manager settings: <enabled-components> has"
5625 + " no name at " + parser.getPositionDescription());
5626 }
5627 } else {
5628 reportSettingsProblem(Log.WARN,
5629 "Unknown element under <enabled-components>: "
5630 + parser.getName());
5631 }
5632 XmlUtils.skipCurrentTag(parser);
5633 }
5634 }
5635
5636 private void readSharedUserLP(XmlPullParser parser)
5637 throws XmlPullParserException, IOException {
5638 String name = null;
5639 String idStr = null;
5640 int pkgFlags = 0;
5641 SharedUserSetting su = null;
5642 try {
5643 name = parser.getAttributeValue(null, "name");
5644 idStr = parser.getAttributeValue(null, "userId");
5645 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
5646 if ("true".equals(parser.getAttributeValue(null, "system"))) {
5647 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
5648 }
5649 if (name == null) {
5650 reportSettingsProblem(Log.WARN,
5651 "Error in package manager settings: <shared-user> has no name at "
5652 + parser.getPositionDescription());
5653 } else if (userId == 0) {
5654 reportSettingsProblem(Log.WARN,
5655 "Error in package manager settings: shared-user "
5656 + name + " has bad userId " + idStr + " at "
5657 + parser.getPositionDescription());
5658 } else {
5659 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
5660 reportSettingsProblem(Log.ERROR,
5661 "Occurred while parsing settings at "
5662 + parser.getPositionDescription());
5663 }
5664 }
5665 } catch (NumberFormatException e) {
5666 reportSettingsProblem(Log.WARN,
5667 "Error in package manager settings: package "
5668 + name + " has bad userId " + idStr + " at "
5669 + parser.getPositionDescription());
5670 };
5671
5672 if (su != null) {
5673 int outerDepth = parser.getDepth();
5674 int type;
5675 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5676 && (type != XmlPullParser.END_TAG
5677 || parser.getDepth() > outerDepth)) {
5678 if (type == XmlPullParser.END_TAG
5679 || type == XmlPullParser.TEXT) {
5680 continue;
5681 }
5682
5683 String tagName = parser.getName();
5684 if (tagName.equals("sigs")) {
5685 su.signatures.readXml(parser, mPastSignatures);
5686 } else if (tagName.equals("perms")) {
5687 readGrantedPermissionsLP(parser, su.loadedPermissions);
5688 } else {
5689 reportSettingsProblem(Log.WARN,
5690 "Unknown element under <shared-user>: "
5691 + parser.getName());
5692 XmlUtils.skipCurrentTag(parser);
5693 }
5694 }
5695
5696 } else {
5697 XmlUtils.skipCurrentTag(parser);
5698 }
5699 }
5700
5701 private void readGrantedPermissionsLP(XmlPullParser parser,
5702 HashSet<String> outPerms) throws IOException, XmlPullParserException {
5703 int outerDepth = parser.getDepth();
5704 int type;
5705 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5706 && (type != XmlPullParser.END_TAG
5707 || parser.getDepth() > outerDepth)) {
5708 if (type == XmlPullParser.END_TAG
5709 || type == XmlPullParser.TEXT) {
5710 continue;
5711 }
5712
5713 String tagName = parser.getName();
5714 if (tagName.equals("item")) {
5715 String name = parser.getAttributeValue(null, "name");
5716 if (name != null) {
5717 outPerms.add(name.intern());
5718 } else {
5719 reportSettingsProblem(Log.WARN,
5720 "Error in package manager settings: <perms> has"
5721 + " no name at " + parser.getPositionDescription());
5722 }
5723 } else {
5724 reportSettingsProblem(Log.WARN,
5725 "Unknown element under <perms>: "
5726 + parser.getName());
5727 }
5728 XmlUtils.skipCurrentTag(parser);
5729 }
5730 }
5731
5732 private void readPreferredPackagesLP(XmlPullParser parser)
5733 throws XmlPullParserException, IOException {
5734 int outerDepth = parser.getDepth();
5735 int type;
5736 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5737 && (type != XmlPullParser.END_TAG
5738 || parser.getDepth() > outerDepth)) {
5739 if (type == XmlPullParser.END_TAG
5740 || type == XmlPullParser.TEXT) {
5741 continue;
5742 }
5743
5744 String tagName = parser.getName();
5745 if (tagName.equals("item")) {
5746 String name = parser.getAttributeValue(null, "name");
5747 if (name != null) {
5748 mPendingPreferredPackages.add(name);
5749 } else {
5750 reportSettingsProblem(Log.WARN,
5751 "Error in package manager settings: <preferred-package> has no name at "
5752 + parser.getPositionDescription());
5753 }
5754 } else {
5755 reportSettingsProblem(Log.WARN,
5756 "Unknown element under <preferred-packages>: "
5757 + parser.getName());
5758 }
5759 XmlUtils.skipCurrentTag(parser);
5760 }
5761 }
5762
5763 private void readPreferredActivitiesLP(XmlPullParser parser)
5764 throws XmlPullParserException, IOException {
5765 int outerDepth = parser.getDepth();
5766 int type;
5767 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5768 && (type != XmlPullParser.END_TAG
5769 || parser.getDepth() > outerDepth)) {
5770 if (type == XmlPullParser.END_TAG
5771 || type == XmlPullParser.TEXT) {
5772 continue;
5773 }
5774
5775 String tagName = parser.getName();
5776 if (tagName.equals("item")) {
5777 PreferredActivity pa = new PreferredActivity(parser);
5778 if (pa.mParseError == null) {
5779 mPreferredActivities.addFilter(pa);
5780 } else {
5781 reportSettingsProblem(Log.WARN,
5782 "Error in package manager settings: <preferred-activity> "
5783 + pa.mParseError + " at "
5784 + parser.getPositionDescription());
5785 }
5786 } else {
5787 reportSettingsProblem(Log.WARN,
5788 "Unknown element under <preferred-activities>: "
5789 + parser.getName());
5790 XmlUtils.skipCurrentTag(parser);
5791 }
5792 }
5793 }
5794
5795 // Returns -1 if we could not find an available UserId to assign
5796 private int newUserIdLP(Object obj) {
5797 // Let's be stupidly inefficient for now...
5798 final int N = mUserIds.size();
5799 for (int i=0; i<N; i++) {
5800 if (mUserIds.get(i) == null) {
5801 mUserIds.set(i, obj);
5802 return FIRST_APPLICATION_UID + i;
5803 }
5804 }
5805
5806 // None left?
5807 if (N >= MAX_APPLICATION_UIDS) {
5808 return -1;
5809 }
5810
5811 mUserIds.add(obj);
5812 return FIRST_APPLICATION_UID + N;
5813 }
5814
5815 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
5816 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
5817 if (Config.LOGV) {
5818 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
5819 + " componentName = " + componentInfo.name);
5820 Log.v(TAG, "enabledComponents: "
5821 + Arrays.toString(packageSettings.enabledComponents.toArray()));
5822 Log.v(TAG, "disabledComponents: "
5823 + Arrays.toString(packageSettings.disabledComponents.toArray()));
5824 }
5825 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
5826 || ((componentInfo.enabled
5827 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
5828 || (componentInfo.applicationInfo.enabled
5829 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
5830 && !packageSettings.disabledComponents.contains(componentInfo.name))
5831 || packageSettings.enabledComponents.contains(componentInfo.name));
5832 }
5833 }
5834}