2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.pm;
19 import static android.Manifest.permission.GRANT_REVOKE_PERMISSIONS;
20 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
21 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
22 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
23 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
24 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
25 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
26 import static android.content.pm.PackageManager.INSTALL_EXTERNAL;
27 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
28 import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
29 import static android.content.pm.PackageManager.INSTALL_FAILED_DEXOPT;
30 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
31 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
32 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
33 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
34 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
35 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
36 import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
37 import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
38 import static android.content.pm.PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
39 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
40 import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY;
41 import static android.content.pm.PackageManager.INSTALL_FAILED_UID_CHANGED;
42 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
43 import static android.content.pm.PackageManager.INSTALL_FAILED_USER_RESTRICTED;
44 import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
45 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
46 import static android.content.pm.PackageParser.isApkFile;
47 import static android.os.Process.PACKAGE_INFO_GID;
48 import static android.os.Process.SYSTEM_UID;
49 import static android.system.OsConstants.O_CREAT;
50 import static android.system.OsConstants.O_RDWR;
51 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
52 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
53 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
54 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
55 import static com.android.internal.util.ArrayUtils.appendInt;
56 import static com.android.internal.util.ArrayUtils.removeInt;
58 import android.util.ArrayMap;
60 import com.android.internal.R;
61 import com.android.internal.app.IMediaContainerService;
62 import com.android.internal.app.ResolverActivity;
63 import com.android.internal.content.NativeLibraryHelper;
64 import com.android.internal.content.PackageHelper;
65 import com.android.internal.os.IParcelFileDescriptorFactory;
66 import com.android.internal.util.ArrayUtils;
67 import com.android.internal.util.FastPrintWriter;
68 import com.android.internal.util.FastXmlSerializer;
69 import com.android.internal.util.IndentingPrintWriter;
70 import com.android.server.EventLogTags;
71 import com.android.server.IntentResolver;
72 import com.android.server.LocalServices;
73 import com.android.server.ServiceThread;
74 import com.android.server.SystemConfig;
75 import com.android.server.Watchdog;
76 import com.android.server.pm.Settings.DatabaseVersion;
77 import com.android.server.storage.DeviceStorageMonitorInternal;
79 import org.xmlpull.v1.XmlSerializer;
81 import android.app.ActivityManager;
82 import android.app.ActivityManagerNative;
83 import android.app.AppGlobals;
84 import android.app.IActivityManager;
85 import android.app.admin.IDevicePolicyManager;
86 import android.app.backup.IBackupManager;
87 import android.app.usage.UsageStats;
88 import android.app.usage.UsageStatsManager;
89 import android.content.BroadcastReceiver;
90 import android.content.ComponentName;
91 import android.content.Context;
92 import android.content.IIntentReceiver;
93 import android.content.Intent;
94 import android.content.IntentFilter;
95 import android.content.IntentSender;
96 import android.content.IntentSender.SendIntentException;
97 import android.content.ServiceConnection;
98 import android.content.pm.ActivityInfo;
99 import android.content.pm.ApplicationInfo;
100 import android.content.pm.FeatureInfo;
101 import android.content.pm.IPackageDataObserver;
102 import android.content.pm.IPackageDeleteObserver;
103 import android.content.pm.IPackageDeleteObserver2;
104 import android.content.pm.IPackageInstallObserver2;
105 import android.content.pm.IPackageInstaller;
106 import android.content.pm.IPackageManager;
107 import android.content.pm.IPackageMoveObserver;
108 import android.content.pm.IPackageStatsObserver;
109 import android.content.pm.InstrumentationInfo;
110 import android.content.pm.KeySet;
111 import android.content.pm.ManifestDigest;
112 import android.content.pm.PackageCleanItem;
113 import android.content.pm.PackageInfo;
114 import android.content.pm.PackageInfoLite;
115 import android.content.pm.PackageInstaller;
116 import android.content.pm.PackageManager;
117 import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
118 import android.content.pm.PackageParser.ActivityIntentInfo;
119 import android.content.pm.PackageParser.PackageLite;
120 import android.content.pm.PackageParser.PackageParserException;
121 import android.content.pm.PackageParser;
122 import android.content.pm.PackageStats;
123 import android.content.pm.PackageUserState;
124 import android.content.pm.ParceledListSlice;
125 import android.content.pm.PermissionGroupInfo;
126 import android.content.pm.PermissionInfo;
127 import android.content.pm.ProviderInfo;
128 import android.content.pm.ResolveInfo;
129 import android.content.pm.ServiceInfo;
130 import android.content.pm.Signature;
131 import android.content.pm.UserInfo;
132 import android.content.pm.VerificationParams;
133 import android.content.pm.VerifierDeviceIdentity;
134 import android.content.pm.VerifierInfo;
135 import android.content.res.Resources;
136 import android.hardware.display.DisplayManager;
137 import android.net.Uri;
138 import android.os.Binder;
139 import android.os.Build;
140 import android.os.Bundle;
141 import android.os.Environment;
142 import android.os.Environment.UserEnvironment;
143 import android.os.storage.StorageManager;
144 import android.os.Debug;
145 import android.os.FileUtils;
146 import android.os.Handler;
147 import android.os.IBinder;
148 import android.os.Looper;
149 import android.os.Message;
150 import android.os.Parcel;
151 import android.os.ParcelFileDescriptor;
152 import android.os.Process;
153 import android.os.RemoteException;
154 import android.os.SELinux;
155 import android.os.ServiceManager;
156 import android.os.SystemClock;
157 import android.os.SystemProperties;
158 import android.os.UserHandle;
159 import android.os.UserManager;
160 import android.security.KeyStore;
161 import android.security.SystemKeyStore;
162 import android.system.ErrnoException;
163 import android.system.Os;
164 import android.system.StructStat;
165 import android.text.TextUtils;
166 import android.util.ArraySet;
167 import android.util.AtomicFile;
168 import android.util.DisplayMetrics;
169 import android.util.EventLog;
170 import android.util.ExceptionUtils;
171 import android.util.Log;
172 import android.util.LogPrinter;
173 import android.util.PrintStreamPrinter;
174 import android.util.Slog;
175 import android.util.SparseArray;
176 import android.util.SparseBooleanArray;
177 import android.view.Display;
179 import java.io.BufferedInputStream;
180 import java.io.BufferedOutputStream;
181 import java.io.BufferedReader;
183 import java.io.FileDescriptor;
184 import java.io.FileInputStream;
185 import java.io.FileNotFoundException;
186 import java.io.FileOutputStream;
187 import java.io.FileReader;
188 import java.io.FilenameFilter;
189 import java.io.IOException;
190 import java.io.InputStream;
191 import java.io.PrintWriter;
192 import java.nio.charset.StandardCharsets;
193 import java.security.NoSuchAlgorithmException;
194 import java.security.PublicKey;
195 import java.security.cert.CertificateEncodingException;
196 import java.security.cert.CertificateException;
197 import java.text.SimpleDateFormat;
198 import java.util.ArrayList;
199 import java.util.Arrays;
200 import java.util.Collection;
201 import java.util.Collections;
202 import java.util.Comparator;
203 import java.util.Date;
204 import java.util.Iterator;
205 import java.util.List;
206 import java.util.Map;
207 import java.util.Objects;
208 import java.util.Set;
209 import java.util.concurrent.atomic.AtomicBoolean;
210 import java.util.concurrent.atomic.AtomicLong;
212 import dalvik.system.DexFile;
213 import dalvik.system.StaleDexCacheError;
214 import dalvik.system.VMRuntime;
216 import libcore.io.IoUtils;
217 import libcore.util.EmptyArray;
220 * Keep track of all those .apks everywhere.
222 * This is very central to the platform's security; please run the unit
223 * tests whenever making modifications here:
225 mmm frameworks/base/tests/AndroidTests
226 adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
227 adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
231 public class PackageManagerService extends IPackageManager.Stub {
232 static final String TAG = "PackageManager";
233 static final boolean DEBUG_SETTINGS = false;
234 static final boolean DEBUG_PREFERRED = false;
235 static final boolean DEBUG_UPGRADE = false;
236 private static final boolean DEBUG_INSTALL = false;
237 private static final boolean DEBUG_REMOVE = false;
238 private static final boolean DEBUG_BROADCASTS = false;
239 private static final boolean DEBUG_SHOW_INFO = false;
240 private static final boolean DEBUG_PACKAGE_INFO = false;
241 private static final boolean DEBUG_INTENT_MATCHING = false;
242 private static final boolean DEBUG_PACKAGE_SCANNING = false;
243 private static final boolean DEBUG_VERIFY = false;
244 private static final boolean DEBUG_DEXOPT = false;
245 private static final boolean DEBUG_ABI_SELECTION = false;
247 private static final int RADIO_UID = Process.PHONE_UID;
248 private static final int LOG_UID = Process.LOG_UID;
249 private static final int NFC_UID = Process.NFC_UID;
250 private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
251 private static final int SHELL_UID = Process.SHELL_UID;
253 // Cap the size of permission trees that 3rd party apps can define
254 private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768; // characters of text
256 // Suffix used during package installation when copying/moving
257 // package apks to install directory.
258 private static final String INSTALL_PACKAGE_SUFFIX = "-";
260 static final int SCAN_NO_DEX = 1<<1;
261 static final int SCAN_FORCE_DEX = 1<<2;
262 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
263 static final int SCAN_NEW_INSTALL = 1<<4;
264 static final int SCAN_NO_PATHS = 1<<5;
265 static final int SCAN_UPDATE_TIME = 1<<6;
266 static final int SCAN_DEFER_DEX = 1<<7;
267 static final int SCAN_BOOTING = 1<<8;
268 static final int SCAN_TRUSTED_OVERLAY = 1<<9;
269 static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
270 static final int SCAN_REPLACING = 1<<11;
272 static final int REMOVE_CHATTY = 1<<16;
275 * Timeout (in milliseconds) after which the watchdog should declare that
276 * our handler thread is wedged. The usual default for such things is one
277 * minute but we sometimes do very lengthy I/O operations on this thread,
278 * such as installing multi-gigabyte applications, so ours needs to be longer.
280 private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
283 * Whether verification is enabled by default.
285 private static final boolean DEFAULT_VERIFY_ENABLE = true;
288 * The default maximum time to wait for the verification agent to return in
291 private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
294 * The default response for package verification timeout.
296 * This can be either PackageManager.VERIFICATION_ALLOW or
297 * PackageManager.VERIFICATION_REJECT.
299 private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
301 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
303 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
304 DEFAULT_CONTAINER_PACKAGE,
305 "com.android.defcontainer.DefaultContainerService");
307 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
309 private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
311 private static String sPreferredInstructionSet;
313 final ServiceThread mHandlerThread;
315 private static final String IDMAP_PREFIX = "/data/resource-cache/";
316 private static final String IDMAP_SUFFIX = "@idmap";
318 final PackageHandler mHandler;
321 * Messages for {@link #mHandler} that need to wait for system ready before
324 private ArrayList<Message> mPostSystemReadyMessages;
326 final int mSdkVersion = Build.VERSION.SDK_INT;
328 final Context mContext;
329 final boolean mFactoryTest;
330 final boolean mOnlyCore;
331 final boolean mLazyDexOpt;
332 final long mDexOptLRUThresholdInMills;
333 final DisplayMetrics mMetrics;
334 final int mDefParseFlags;
335 final String[] mSeparateProcesses;
336 final boolean mIsUpgrade;
338 // This is where all application persistent data goes.
339 final File mAppDataDir;
341 // This is where all application persistent data goes for secondary users.
342 final File mUserAppDataDir;
344 /** The location for ASEC container files on internal storage. */
345 final String mAsecInternalPath;
347 // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
348 // LOCK HELD. Can be called with mInstallLock held.
349 final Installer mInstaller;
351 /** Directory where installed third-party apps stored */
352 final File mAppInstallDir;
355 * Directory to which applications installed internally have their
356 * 32 bit native libraries copied.
358 private File mAppLib32InstallDir;
360 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
362 final File mDrmAppPrivateInstallDir;
364 // ----------------------------------------------------------------
366 // Lock for state used when installing and doing other long running
367 // operations. Methods that must be called with this lock held have
369 final Object mInstallLock = new Object();
371 // ----------------------------------------------------------------
373 // Keys are String (package name), values are Package. This also serves
374 // as the lock for the global state. Methods that must be called with
375 // this lock held have the prefix "LP".
376 final ArrayMap<String, PackageParser.Package> mPackages =
377 new ArrayMap<String, PackageParser.Package>();
379 // Tracks available target package names -> overlay package paths.
380 final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
381 new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
383 final Settings mSettings;
384 boolean mRestoredSettings;
386 // System configuration read by SystemConfig.
387 final int[] mGlobalGids;
388 final SparseArray<ArraySet<String>> mSystemPermissions;
389 final ArrayMap<String, FeatureInfo> mAvailableFeatures;
391 // If mac_permissions.xml was found for seinfo labeling.
392 boolean mFoundPolicyFile;
394 // If a recursive restorecon of /data/data/<pkg> is needed.
395 private boolean mShouldRestoreconData = SELinuxMMAC.shouldRestorecon();
397 public static final class SharedLibraryEntry {
398 public final String path;
399 public final String apk;
401 SharedLibraryEntry(String _path, String _apk) {
407 // Currently known shared libraries.
408 final ArrayMap<String, SharedLibraryEntry> mSharedLibraries =
409 new ArrayMap<String, SharedLibraryEntry>();
411 // All available activities, for your resolving pleasure.
412 final ActivityIntentResolver mActivities =
413 new ActivityIntentResolver();
415 // All available receivers, for your resolving pleasure.
416 final ActivityIntentResolver mReceivers =
417 new ActivityIntentResolver();
419 // All available services, for your resolving pleasure.
420 final ServiceIntentResolver mServices = new ServiceIntentResolver();
422 // All available providers, for your resolving pleasure.
423 final ProviderIntentResolver mProviders = new ProviderIntentResolver();
425 // Mapping from provider base names (first directory in content URI codePath)
426 // to the provider information.
427 final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority =
428 new ArrayMap<String, PackageParser.Provider>();
430 // Mapping from instrumentation class names to info about them.
431 final ArrayMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
432 new ArrayMap<ComponentName, PackageParser.Instrumentation>();
434 // Mapping from permission names to info about them.
435 final ArrayMap<String, PackageParser.PermissionGroup> mPermissionGroups =
436 new ArrayMap<String, PackageParser.PermissionGroup>();
438 // Packages whose data we have transfered into another package, thus
439 // should no longer exist.
440 final ArraySet<String> mTransferedPackages = new ArraySet<String>();
442 // Broadcast actions that are only available to the system.
443 final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>();
445 /** List of packages waiting for verification. */
446 final SparseArray<PackageVerificationState> mPendingVerification
447 = new SparseArray<PackageVerificationState>();
449 /** Set of packages associated with each app op permission. */
450 final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
452 final PackageInstallerService mInstallerService;
454 ArraySet<PackageParser.Package> mDeferredDexOpt = null;
456 // Cache of users who need badging.
457 SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
459 /** Token for keys in mPendingVerification. */
460 private int mPendingVerificationToken = 0;
462 volatile boolean mSystemReady;
463 volatile boolean mSafeMode;
464 volatile boolean mHasSystemUidErrors;
466 ApplicationInfo mAndroidApplication;
467 final ActivityInfo mResolveActivity = new ActivityInfo();
468 final ResolveInfo mResolveInfo = new ResolveInfo();
469 ComponentName mResolveComponentName;
470 PackageParser.Package mPlatformPackage;
471 ComponentName mCustomResolverComponentName;
473 boolean mResolverReplaced = false;
475 // Set of pending broadcasts for aggregating enable/disable of components.
476 static class PendingPackageBroadcasts {
477 // for each user id, a map of <package name -> components within that package>
478 final SparseArray<ArrayMap<String, ArrayList<String>>> mUidMap;
480 public PendingPackageBroadcasts() {
481 mUidMap = new SparseArray<ArrayMap<String, ArrayList<String>>>(2);
484 public ArrayList<String> get(int userId, String packageName) {
485 ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId);
486 return packages.get(packageName);
489 public void put(int userId, String packageName, ArrayList<String> components) {
490 ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId);
491 packages.put(packageName, components);
494 public void remove(int userId, String packageName) {
495 ArrayMap<String, ArrayList<String>> packages = mUidMap.get(userId);
496 if (packages != null) {
497 packages.remove(packageName);
501 public void remove(int userId) {
502 mUidMap.remove(userId);
505 public int userIdCount() {
506 return mUidMap.size();
509 public int userIdAt(int n) {
510 return mUidMap.keyAt(n);
513 public ArrayMap<String, ArrayList<String>> packagesForUserId(int userId) {
514 return mUidMap.get(userId);
518 // total number of pending broadcast entries across all userIds
520 for (int i = 0; i< mUidMap.size(); i++) {
521 num += mUidMap.valueAt(i).size();
526 public void clear() {
530 private ArrayMap<String, ArrayList<String>> getOrAllocate(int userId) {
531 ArrayMap<String, ArrayList<String>> map = mUidMap.get(userId);
533 map = new ArrayMap<String, ArrayList<String>>();
534 mUidMap.put(userId, map);
539 final PendingPackageBroadcasts mPendingBroadcasts = new PendingPackageBroadcasts();
541 // Service Connection to remote media container service to copy
542 // package uri's from external media onto secure containers
543 // or internal storage.
544 private IMediaContainerService mContainerService = null;
546 static final int SEND_PENDING_BROADCAST = 1;
547 static final int MCS_BOUND = 3;
548 static final int END_COPY = 4;
549 static final int INIT_COPY = 5;
550 static final int MCS_UNBIND = 6;
551 static final int START_CLEANING_PACKAGE = 7;
552 static final int FIND_INSTALL_LOC = 8;
553 static final int POST_INSTALL = 9;
554 static final int MCS_RECONNECT = 10;
555 static final int MCS_GIVE_UP = 11;
556 static final int UPDATED_MEDIA_STATUS = 12;
557 static final int WRITE_SETTINGS = 13;
558 static final int WRITE_PACKAGE_RESTRICTIONS = 14;
559 static final int PACKAGE_VERIFIED = 15;
560 static final int CHECK_PENDING_VERIFICATION = 16;
562 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
564 // Delay time in millisecs
565 static final int BROADCAST_DELAY = 10 * 1000;
567 static UserManagerService sUserManager;
569 // Stores a list of users whose package restrictions file needs to be updated
570 private ArraySet<Integer> mDirtyUsers = new ArraySet<Integer>();
572 final private DefaultContainerConnection mDefContainerConn =
573 new DefaultContainerConnection();
574 class DefaultContainerConnection implements ServiceConnection {
575 public void onServiceConnected(ComponentName name, IBinder service) {
576 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
577 IMediaContainerService imcs =
578 IMediaContainerService.Stub.asInterface(service);
579 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
582 public void onServiceDisconnected(ComponentName name) {
583 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
587 // Recordkeeping of restore-after-install operations that are currently in flight
588 // between the Package Manager and the Backup Manager
589 class PostInstallData {
590 public InstallArgs args;
591 public PackageInstalledInfo res;
593 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
598 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
599 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
601 private final String mRequiredVerifierPackage;
603 private final PackageUsage mPackageUsage = new PackageUsage();
605 private class PackageUsage {
606 private static final int WRITE_INTERVAL
607 = (DEBUG_DEXOPT) ? 0 : 30*60*1000; // 30m in ms
609 private final Object mFileLock = new Object();
610 private final AtomicLong mLastWritten = new AtomicLong(0);
611 private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
613 private boolean mIsHistoricalPackageUsageAvailable = true;
615 boolean isHistoricalPackageUsageAvailable() {
616 return mIsHistoricalPackageUsageAvailable;
619 void write(boolean force) {
624 if (SystemClock.elapsedRealtime() - mLastWritten.get() < WRITE_INTERVAL
628 if (mBackgroundWriteRunning.compareAndSet(false, true)) {
629 new Thread("PackageUsage_DiskWriter") {
635 mBackgroundWriteRunning.set(false);
642 private void writeInternal() {
643 synchronized (mPackages) {
644 synchronized (mFileLock) {
645 AtomicFile file = getFile();
646 FileOutputStream f = null;
648 f = file.startWrite();
649 BufferedOutputStream out = new BufferedOutputStream(f);
650 FileUtils.setPermissions(file.getBaseFile().getPath(), 0660, SYSTEM_UID, PACKAGE_INFO_GID);
651 StringBuilder sb = new StringBuilder();
652 for (PackageParser.Package pkg : mPackages.values()) {
653 if (pkg.mLastPackageUsageTimeInMills == 0) {
657 sb.append(pkg.packageName);
659 sb.append((long)pkg.mLastPackageUsageTimeInMills);
661 out.write(sb.toString().getBytes(StandardCharsets.US_ASCII));
665 } catch (IOException e) {
669 Log.e(TAG, "Failed to write package usage times", e);
673 mLastWritten.set(SystemClock.elapsedRealtime());
677 synchronized (mFileLock) {
678 AtomicFile file = getFile();
679 BufferedInputStream in = null;
681 in = new BufferedInputStream(file.openRead());
682 StringBuffer sb = new StringBuffer();
684 String packageName = readToken(in, sb, ' ');
685 if (packageName == null) {
688 String timeInMillisString = readToken(in, sb, '\n');
689 if (timeInMillisString == null) {
690 throw new IOException("Failed to find last usage time for package "
693 PackageParser.Package pkg = mPackages.get(packageName);
699 timeInMillis = Long.parseLong(timeInMillisString.toString());
700 } catch (NumberFormatException e) {
701 throw new IOException("Failed to parse " + timeInMillisString
704 pkg.mLastPackageUsageTimeInMills = timeInMillis;
706 } catch (FileNotFoundException expected) {
707 mIsHistoricalPackageUsageAvailable = false;
708 } catch (IOException e) {
709 Log.w(TAG, "Failed to read package usage times", e);
711 IoUtils.closeQuietly(in);
714 mLastWritten.set(SystemClock.elapsedRealtime());
717 private String readToken(InputStream in, StringBuffer sb, char endOfToken)
723 if (sb.length() == 0) {
726 throw new IOException("Unexpected EOF");
728 if (ch == endOfToken) {
729 return sb.toString();
735 private AtomicFile getFile() {
736 File dataDir = Environment.getDataDirectory();
737 File systemDir = new File(dataDir, "system");
738 File fname = new File(systemDir, "package-usage.list");
739 return new AtomicFile(fname);
743 class PackageHandler extends Handler {
744 private boolean mBound = false;
745 final ArrayList<HandlerParams> mPendingInstalls =
746 new ArrayList<HandlerParams>();
748 private boolean connectToService() {
749 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
750 " DefaultContainerService");
751 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
752 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
753 if (mContext.bindServiceAsUser(service, mDefContainerConn,
754 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
755 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
759 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
763 private void disconnectService() {
764 mContainerService = null;
766 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
767 mContext.unbindService(mDefContainerConn);
768 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
771 PackageHandler(Looper looper) {
775 public void handleMessage(Message msg) {
777 doHandleMessage(msg);
779 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
783 void doHandleMessage(Message msg) {
786 HandlerParams params = (HandlerParams) msg.obj;
787 int idx = mPendingInstalls.size();
788 if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
789 // If a bind was already initiated we dont really
790 // need to do anything. The pending install
791 // will be processed later on.
793 // If this is the only one pending we might
794 // have to bind to the service again.
795 if (!connectToService()) {
796 Slog.e(TAG, "Failed to bind to media container service");
797 params.serviceError();
800 // Once we bind to the service, the first
801 // pending request will be processed.
802 mPendingInstalls.add(idx, params);
805 mPendingInstalls.add(idx, params);
806 // Already bound to the service. Just make
807 // sure we trigger off processing the first request.
809 mHandler.sendEmptyMessage(MCS_BOUND);
815 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
816 if (msg.obj != null) {
817 mContainerService = (IMediaContainerService) msg.obj;
819 if (mContainerService == null) {
820 // Something seriously wrong. Bail out
821 Slog.e(TAG, "Cannot bind to media container service");
822 for (HandlerParams params : mPendingInstalls) {
823 // Indicate service bind error
824 params.serviceError();
826 mPendingInstalls.clear();
827 } else if (mPendingInstalls.size() > 0) {
828 HandlerParams params = mPendingInstalls.get(0);
829 if (params != null) {
830 if (params.startCopy()) {
831 // We are done... look for more work or to
833 if (DEBUG_SD_INSTALL) Log.i(TAG,
834 "Checking for more work or unbind...");
835 // Delete pending install
836 if (mPendingInstalls.size() > 0) {
837 mPendingInstalls.remove(0);
839 if (mPendingInstalls.size() == 0) {
841 if (DEBUG_SD_INSTALL) Log.i(TAG,
842 "Posting delayed MCS_UNBIND");
843 removeMessages(MCS_UNBIND);
844 Message ubmsg = obtainMessage(MCS_UNBIND);
845 // Unbind after a little delay, to avoid
846 // continual thrashing.
847 sendMessageDelayed(ubmsg, 10000);
850 // There are more pending requests in queue.
851 // Just post MCS_BOUND message to trigger processing
852 // of next pending install.
853 if (DEBUG_SD_INSTALL) Log.i(TAG,
854 "Posting MCS_BOUND for next work");
855 mHandler.sendEmptyMessage(MCS_BOUND);
860 // Should never happen ideally.
861 Slog.w(TAG, "Empty queue");
865 case MCS_RECONNECT: {
866 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
867 if (mPendingInstalls.size() > 0) {
871 if (!connectToService()) {
872 Slog.e(TAG, "Failed to bind to media container service");
873 for (HandlerParams params : mPendingInstalls) {
874 // Indicate service bind error
875 params.serviceError();
877 mPendingInstalls.clear();
883 // If there is no actual work left, then time to unbind.
884 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
886 if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
888 if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
892 } else if (mPendingInstalls.size() > 0) {
893 // There are more pending requests in queue.
894 // Just post MCS_BOUND message to trigger processing
895 // of next pending install.
896 mHandler.sendEmptyMessage(MCS_BOUND);
902 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
903 mPendingInstalls.remove(0);
906 case SEND_PENDING_BROADCAST: {
908 ArrayList<String> components[];
911 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
912 synchronized (mPackages) {
913 if (mPendingBroadcasts == null) {
916 size = mPendingBroadcasts.size();
918 // Nothing to be done. Just return
921 packages = new String[size];
922 components = new ArrayList[size];
923 uids = new int[size];
924 int i = 0; // filling out the above arrays
926 for (int n = 0; n < mPendingBroadcasts.userIdCount(); n++) {
927 int packageUserId = mPendingBroadcasts.userIdAt(n);
928 Iterator<Map.Entry<String, ArrayList<String>>> it
929 = mPendingBroadcasts.packagesForUserId(packageUserId)
930 .entrySet().iterator();
931 while (it.hasNext() && i < size) {
932 Map.Entry<String, ArrayList<String>> ent = it.next();
933 packages[i] = ent.getKey();
934 components[i] = ent.getValue();
935 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
936 uids[i] = (ps != null)
937 ? UserHandle.getUid(packageUserId, ps.appId)
943 mPendingBroadcasts.clear();
946 for (int i = 0; i < size; i++) {
947 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
949 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
952 case START_CLEANING_PACKAGE: {
953 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
954 final String packageName = (String)msg.obj;
955 final int userId = msg.arg1;
956 final boolean andCode = msg.arg2 != 0;
957 synchronized (mPackages) {
958 if (userId == UserHandle.USER_ALL) {
959 int[] users = sUserManager.getUserIds();
960 for (int user : users) {
961 mSettings.addPackageToCleanLPw(
962 new PackageCleanItem(user, packageName, andCode));
965 mSettings.addPackageToCleanLPw(
966 new PackageCleanItem(userId, packageName, andCode));
969 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
970 startCleaningPackages();
973 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
974 PostInstallData data = mRunningInstalls.get(msg.arg1);
975 mRunningInstalls.delete(msg.arg1);
976 boolean deleteOld = false;
979 InstallArgs args = data.args;
980 PackageInstalledInfo res = data.res;
982 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
983 res.removedInfo.sendBroadcast(false, true, false);
984 Bundle extras = new Bundle(1);
985 extras.putInt(Intent.EXTRA_UID, res.uid);
986 // Determine the set of users who are adding this
987 // package for the first time vs. those who are seeing
990 int[] updateUsers = new int[0];
991 if (res.origUsers == null || res.origUsers.length == 0) {
992 firstUsers = res.newUsers;
994 firstUsers = new int[0];
995 for (int i=0; i<res.newUsers.length; i++) {
996 int user = res.newUsers[i];
997 boolean isNew = true;
998 for (int j=0; j<res.origUsers.length; j++) {
999 if (res.origUsers[j] == user) {
1005 int[] newFirst = new int[firstUsers.length+1];
1006 System.arraycopy(firstUsers, 0, newFirst, 0,
1008 newFirst[firstUsers.length] = user;
1009 firstUsers = newFirst;
1011 int[] newUpdate = new int[updateUsers.length+1];
1012 System.arraycopy(updateUsers, 0, newUpdate, 0,
1013 updateUsers.length);
1014 newUpdate[updateUsers.length] = user;
1015 updateUsers = newUpdate;
1019 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
1020 res.pkg.applicationInfo.packageName,
1021 extras, null, null, firstUsers);
1022 final boolean update = res.removedInfo.removedPackage != null;
1024 extras.putBoolean(Intent.EXTRA_REPLACING, true);
1026 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
1027 res.pkg.applicationInfo.packageName,
1028 extras, null, null, updateUsers);
1030 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
1031 res.pkg.applicationInfo.packageName,
1032 extras, null, null, updateUsers);
1033 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
1035 res.pkg.applicationInfo.packageName, null, updateUsers);
1037 // treat asec-hosted packages like removable media on upgrade
1038 if (isForwardLocked(res.pkg) || isExternal(res.pkg)) {
1039 if (DEBUG_INSTALL) {
1040 Slog.i(TAG, "upgrading pkg " + res.pkg
1041 + " is ASEC-hosted -> AVAILABLE");
1043 int[] uidArray = new int[] { res.pkg.applicationInfo.uid };
1044 ArrayList<String> pkgList = new ArrayList<String>(1);
1045 pkgList.add(res.pkg.applicationInfo.packageName);
1046 sendResourcesChangedBroadcast(true, true,
1047 pkgList,uidArray, null);
1050 if (res.removedInfo.args != null) {
1051 // Remove the replaced package's older resources safely now
1055 // Log current value of "unknown sources" setting
1056 EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
1057 getUnknownSourcesSettings());
1059 // Force a gc to clear up things
1060 Runtime.getRuntime().gc();
1061 // We delete after a gc for applications on sdcard.
1063 synchronized (mInstallLock) {
1064 res.removedInfo.args.doPostDeleteLI(true);
1067 if (args.observer != null) {
1069 Bundle extras = extrasForInstallResult(res);
1070 args.observer.onPackageInstalled(res.name, res.returnCode,
1071 res.returnMsg, extras);
1072 } catch (RemoteException e) {
1073 Slog.i(TAG, "Observer no longer exists.");
1077 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
1080 case UPDATED_MEDIA_STATUS: {
1081 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
1082 boolean reportStatus = msg.arg1 == 1;
1083 boolean doGc = msg.arg2 == 1;
1084 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
1086 // Force a gc to clear up stale containers.
1087 Runtime.getRuntime().gc();
1089 if (msg.obj != null) {
1090 @SuppressWarnings("unchecked")
1091 Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
1092 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
1093 // Unload containers
1094 unloadAllContainers(args);
1098 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
1099 PackageHelper.getMountService().finishMediaUpdate();
1100 } catch (RemoteException e) {
1101 Log.e(TAG, "MountService not running?");
1105 case WRITE_SETTINGS: {
1106 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
1107 synchronized (mPackages) {
1108 removeMessages(WRITE_SETTINGS);
1109 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
1110 mSettings.writeLPr();
1111 mDirtyUsers.clear();
1113 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1115 case WRITE_PACKAGE_RESTRICTIONS: {
1116 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
1117 synchronized (mPackages) {
1118 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
1119 for (int userId : mDirtyUsers) {
1120 mSettings.writePackageRestrictionsLPr(userId);
1122 mDirtyUsers.clear();
1124 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1126 case CHECK_PENDING_VERIFICATION: {
1127 final int verificationId = msg.arg1;
1128 final PackageVerificationState state = mPendingVerification.get(verificationId);
1130 if ((state != null) && !state.timeoutExtended()) {
1131 final InstallArgs args = state.getInstallArgs();
1132 final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
1134 Slog.i(TAG, "Verification timed out for " + originUri);
1135 mPendingVerification.remove(verificationId);
1137 int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
1139 if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
1140 Slog.i(TAG, "Continuing with installation of " + originUri);
1141 state.setVerifierResponse(Binder.getCallingUid(),
1142 PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
1143 broadcastPackageVerified(verificationId, originUri,
1144 PackageManager.VERIFICATION_ALLOW,
1145 state.getInstallArgs().getUser());
1147 ret = args.copyApk(mContainerService, true);
1148 } catch (RemoteException e) {
1149 Slog.e(TAG, "Could not contact the ContainerService");
1152 broadcastPackageVerified(verificationId, originUri,
1153 PackageManager.VERIFICATION_REJECT,
1154 state.getInstallArgs().getUser());
1157 processPendingInstall(args, ret);
1158 mHandler.sendEmptyMessage(MCS_UNBIND);
1162 case PACKAGE_VERIFIED: {
1163 final int verificationId = msg.arg1;
1165 final PackageVerificationState state = mPendingVerification.get(verificationId);
1166 if (state == null) {
1167 Slog.w(TAG, "Invalid verification token " + verificationId + " received");
1171 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
1173 state.setVerifierResponse(response.callerUid, response.code);
1175 if (state.isVerificationComplete()) {
1176 mPendingVerification.remove(verificationId);
1178 final InstallArgs args = state.getInstallArgs();
1179 final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
1182 if (state.isInstallAllowed()) {
1183 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
1184 broadcastPackageVerified(verificationId, originUri,
1185 response.code, state.getInstallArgs().getUser());
1187 ret = args.copyApk(mContainerService, true);
1188 } catch (RemoteException e) {
1189 Slog.e(TAG, "Could not contact the ContainerService");
1192 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
1195 processPendingInstall(args, ret);
1197 mHandler.sendEmptyMessage(MCS_UNBIND);
1206 Bundle extrasForInstallResult(PackageInstalledInfo res) {
1207 Bundle extras = null;
1208 switch (res.returnCode) {
1209 case PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION: {
1210 extras = new Bundle();
1211 extras.putString(PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION,
1212 res.origPermission);
1213 extras.putString(PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE,
1221 void scheduleWriteSettingsLocked() {
1222 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
1223 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
1227 void scheduleWritePackageRestrictionsLocked(int userId) {
1228 if (!sUserManager.exists(userId)) return;
1229 mDirtyUsers.add(userId);
1230 if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
1231 mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
1235 public static final PackageManagerService main(Context context, Installer installer,
1236 boolean factoryTest, boolean onlyCore) {
1237 PackageManagerService m = new PackageManagerService(context, installer,
1238 factoryTest, onlyCore);
1239 ServiceManager.addService("package", m);
1243 static String[] splitString(String str, char sep) {
1246 while ((i=str.indexOf(sep, i)) >= 0) {
1251 String[] res = new String[count];
1255 while ((i=str.indexOf(sep, i)) >= 0) {
1256 res[count] = str.substring(lastI, i);
1261 res[count] = str.substring(lastI, str.length());
1265 private static void getDefaultDisplayMetrics(Context context, DisplayMetrics metrics) {
1266 DisplayManager displayManager = (DisplayManager) context.getSystemService(
1267 Context.DISPLAY_SERVICE);
1268 displayManager.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics);
1271 public PackageManagerService(Context context, Installer installer,
1272 boolean factoryTest, boolean onlyCore) {
1273 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
1274 SystemClock.uptimeMillis());
1276 if (mSdkVersion <= 0) {
1277 Slog.w(TAG, "**** ro.build.version.sdk not set!");
1281 mFactoryTest = factoryTest;
1282 mOnlyCore = onlyCore;
1283 mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
1284 mMetrics = new DisplayMetrics();
1285 mSettings = new Settings(context);
1286 mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
1287 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1288 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
1289 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1290 mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
1291 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1292 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
1293 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1294 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
1295 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1296 mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
1297 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1299 // TODO: add a property to control this?
1300 long dexOptLRUThresholdInMinutes;
1302 dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
1304 dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
1306 mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
1308 String separateProcesses = SystemProperties.get("debug.separate_processes");
1309 if (separateProcesses != null && separateProcesses.length() > 0) {
1310 if ("*".equals(separateProcesses)) {
1311 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
1312 mSeparateProcesses = null;
1313 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
1316 mSeparateProcesses = separateProcesses.split(",");
1317 Slog.w(TAG, "Running with debug.separate_processes: "
1318 + separateProcesses);
1322 mSeparateProcesses = null;
1325 mInstaller = installer;
1327 getDefaultDisplayMetrics(context, mMetrics);
1329 SystemConfig systemConfig = SystemConfig.getInstance();
1330 mGlobalGids = systemConfig.getGlobalGids();
1331 mSystemPermissions = systemConfig.getSystemPermissions();
1332 mAvailableFeatures = systemConfig.getAvailableFeatures();
1334 synchronized (mInstallLock) {
1336 synchronized (mPackages) {
1337 mHandlerThread = new ServiceThread(TAG,
1338 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
1339 mHandlerThread.start();
1340 mHandler = new PackageHandler(mHandlerThread.getLooper());
1341 Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
1343 File dataDir = Environment.getDataDirectory();
1344 mAppDataDir = new File(dataDir, "data");
1345 mAppInstallDir = new File(dataDir, "app");
1346 mAppLib32InstallDir = new File(dataDir, "app-lib");
1347 mAsecInternalPath = new File(dataDir, "app-asec").getPath();
1348 mUserAppDataDir = new File(dataDir, "user");
1349 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
1351 sUserManager = new UserManagerService(context, this,
1352 mInstallLock, mPackages);
1354 // Propagate permission configuration in to package manager.
1355 ArrayMap<String, SystemConfig.PermissionEntry> permConfig
1356 = systemConfig.getPermissions();
1357 for (int i=0; i<permConfig.size(); i++) {
1358 SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
1359 BasePermission bp = mSettings.mPermissions.get(perm.name);
1361 bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
1362 mSettings.mPermissions.put(perm.name, bp);
1364 if (perm.gids != null) {
1365 bp.gids = appendInts(bp.gids, perm.gids);
1369 ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
1370 for (int i=0; i<libConfig.size(); i++) {
1371 mSharedLibraries.put(libConfig.keyAt(i),
1372 new SharedLibraryEntry(libConfig.valueAt(i), null));
1375 mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
1377 mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false),
1378 mSdkVersion, mOnlyCore);
1380 String customResolverActivity = Resources.getSystem().getString(
1381 R.string.config_customResolverActivity);
1382 if (TextUtils.isEmpty(customResolverActivity)) {
1383 customResolverActivity = null;
1385 mCustomResolverComponentName = ComponentName.unflattenFromString(
1386 customResolverActivity);
1389 long startTime = SystemClock.uptimeMillis();
1391 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
1394 // Set flag to monitor and not change apk file paths when
1395 // scanning install directories.
1396 final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
1398 final ArraySet<String> alreadyDexOpted = new ArraySet<String>();
1401 * Add everything in the in the boot class path to the
1402 * list of process files because dexopt will have been run
1403 * if necessary during zygote startup.
1405 final String bootClassPath = System.getenv("BOOTCLASSPATH");
1406 final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
1408 if (bootClassPath != null) {
1409 String[] bootClassPathElements = splitString(bootClassPath, ':');
1410 for (String element : bootClassPathElements) {
1411 alreadyDexOpted.add(element);
1414 Slog.w(TAG, "No BOOTCLASSPATH found!");
1417 if (systemServerClassPath != null) {
1418 String[] systemServerClassPathElements = splitString(systemServerClassPath, ':');
1419 for (String element : systemServerClassPathElements) {
1420 alreadyDexOpted.add(element);
1423 Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
1426 boolean didDexOptLibraryOrTool = false;
1428 final List<String> allInstructionSets = getAllInstructionSets();
1429 final String[] dexCodeInstructionSets =
1430 getDexCodeInstructionSets(allInstructionSets.toArray(new String[allInstructionSets.size()]));
1433 * Ensure all external libraries have had dexopt run on them.
1435 if (mSharedLibraries.size() > 0) {
1436 // NOTE: For now, we're compiling these system "shared libraries"
1437 // (and framework jars) into all available architectures. It's possible
1438 // to compile them only when we come across an app that uses them (there's
1439 // already logic for that in scanPackageLI) but that adds some complexity.
1440 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
1441 for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
1442 final String lib = libEntry.path;
1448 byte dexoptRequired = DexFile.isDexOptNeededInternal(lib, null,
1449 dexCodeInstructionSet,
1451 if (dexoptRequired != DexFile.UP_TO_DATE) {
1452 alreadyDexOpted.add(lib);
1454 // The list of "shared libraries" we have at this point is
1455 if (dexoptRequired == DexFile.DEXOPT_NEEDED) {
1456 mInstaller.dexopt(lib, Process.SYSTEM_UID, true, dexCodeInstructionSet);
1458 mInstaller.patchoat(lib, Process.SYSTEM_UID, true, dexCodeInstructionSet);
1460 didDexOptLibraryOrTool = true;
1462 } catch (FileNotFoundException e) {
1463 Slog.w(TAG, "Library not found: " + lib);
1464 } catch (IOException e) {
1465 Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
1472 File frameworkDir = new File(Environment.getRootDirectory(), "framework");
1474 // Gross hack for now: we know this file doesn't contain any
1475 // code, so don't dexopt it to avoid the resulting log spew.
1476 alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");
1478 // Gross hack for now: we know this file is only part of
1479 // the boot class path for art, so don't dexopt it to
1480 // avoid the resulting log spew.
1481 alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
1484 * And there are a number of commands implemented in Java, which
1485 * we currently need to do the dexopt on so that they can be
1486 * run from a non-root shell.
1488 String[] frameworkFiles = frameworkDir.list();
1489 if (frameworkFiles != null) {
1490 // TODO: We could compile these only for the most preferred ABI. We should
1491 // first double check that the dex files for these commands are not referenced
1492 // by other system apps.
1493 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
1494 for (int i=0; i<frameworkFiles.length; i++) {
1495 File libPath = new File(frameworkDir, frameworkFiles[i]);
1496 String path = libPath.getPath();
1497 // Skip the file if we already did it.
1498 if (alreadyDexOpted.contains(path)) {
1501 // Skip the file if it is not a type we want to dexopt.
1502 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
1506 byte dexoptRequired = DexFile.isDexOptNeededInternal(path, null,
1507 dexCodeInstructionSet,
1509 if (dexoptRequired == DexFile.DEXOPT_NEEDED) {
1510 mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet);
1511 didDexOptLibraryOrTool = true;
1512 } else if (dexoptRequired == DexFile.PATCHOAT_NEEDED) {
1513 mInstaller.patchoat(path, Process.SYSTEM_UID, true, dexCodeInstructionSet);
1514 didDexOptLibraryOrTool = true;
1516 } catch (FileNotFoundException e) {
1517 Slog.w(TAG, "Jar not found: " + path);
1518 } catch (IOException e) {
1519 Slog.w(TAG, "Exception reading jar: " + path, e);
1525 // Collect vendor overlay packages.
1526 // (Do this before scanning any apps.)
1527 // For security and version matching reason, only consider
1528 // overlay packages if they reside in VENDOR_OVERLAY_DIR.
1529 File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
1530 scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
1531 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
1533 // Find base frameworks (resource packages without code).
1534 scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
1535 | PackageParser.PARSE_IS_SYSTEM_DIR
1536 | PackageParser.PARSE_IS_PRIVILEGED,
1537 scanFlags | SCAN_NO_DEX, 0);
1539 // Collected privileged system packages.
1540 final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
1541 scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
1542 | PackageParser.PARSE_IS_SYSTEM_DIR
1543 | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
1545 // Collect ordinary system packages.
1546 final File systemAppDir = new File(Environment.getRootDirectory(), "app");
1547 scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
1548 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
1550 // Collect all vendor packages.
1551 File vendorAppDir = new File("/vendor/app");
1553 vendorAppDir = vendorAppDir.getCanonicalFile();
1554 } catch (IOException e) {
1555 // failed to look up canonical path, continue with original one
1557 scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
1558 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
1560 // Collect all OEM packages.
1561 final File oemAppDir = new File(Environment.getOemDirectory(), "app");
1562 scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
1563 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
1565 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1566 mInstaller.moveFiles();
1568 // Prune any system packages that no longer exist.
1569 final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
1570 final ArrayMap<String, File> expectingBetter = new ArrayMap<>();
1572 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1573 while (psit.hasNext()) {
1574 PackageSetting ps = psit.next();
1577 * If this is not a system app, it can't be a
1578 * disable system app.
1580 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1585 * If the package is scanned, it's not erased.
1587 final PackageParser.Package scannedPkg = mPackages.get(ps.name);
1588 if (scannedPkg != null) {
1590 * If the system app is both scanned and in the
1591 * disabled packages list, then it must have been
1592 * added via OTA. Remove it from the currently
1593 * scanned package so the previously user-installed
1594 * application can be scanned.
1596 if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
1597 logCriticalInfo(Log.WARN, "Expecting better updated system app for "
1598 + ps.name + "; removing system app. Last known codePath="
1599 + ps.codePathString + ", installStatus=" + ps.installStatus
1600 + ", versionCode=" + ps.versionCode + "; scanned versionCode="
1601 + scannedPkg.mVersionCode);
1602 removePackageLI(ps, true);
1603 expectingBetter.put(ps.name, ps.codePath);
1609 if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
1611 logCriticalInfo(Log.WARN, "System package " + ps.name
1612 + " no longer exists; wiping its data");
1613 removeDataDirsLI(ps.name);
1615 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
1616 if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
1617 possiblyDeletedUpdatedSystemApps.add(ps.name);
1623 //look for any incomplete package installations
1624 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
1626 for(int i = 0; i < deletePkgsList.size(); i++) {
1628 cleanupInstallFailedPackage(deletePkgsList.get(i));
1631 deleteTempPackageFiles();
1633 // Remove any shared userIDs that have no associated packages
1634 mSettings.pruneSharedUsersLPw();
1637 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1638 SystemClock.uptimeMillis());
1639 scanDirLI(mAppInstallDir, 0, scanFlags, 0);
1641 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1645 * Remove disable package settings for any updated system
1646 * apps that were removed via an OTA. If they're not a
1647 * previously-updated app, remove them completely.
1648 * Otherwise, just revoke their system-level permissions.
1650 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
1651 PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
1652 mSettings.removeDisabledSystemPackageLPw(deletedAppName);
1655 if (deletedPkg == null) {
1656 msg = "Updated system package " + deletedAppName
1657 + " no longer exists; wiping its data";
1658 removeDataDirsLI(deletedAppName);
1660 msg = "Updated system app + " + deletedAppName
1661 + " no longer present; removing system privileges for "
1664 deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
1666 PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
1667 deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
1669 logCriticalInfo(Log.WARN, msg);
1673 * Make sure all system apps that we expected to appear on
1674 * the userdata partition actually showed up. If they never
1675 * appeared, crawl back and revive the system version.
1677 for (int i = 0; i < expectingBetter.size(); i++) {
1678 final String packageName = expectingBetter.keyAt(i);
1679 if (!mPackages.containsKey(packageName)) {
1680 final File scanFile = expectingBetter.valueAt(i);
1682 logCriticalInfo(Log.WARN, "Expected better " + packageName
1683 + " but never showed up; reverting to system");
1685 final int reparseFlags;
1686 if (FileUtils.contains(privilegedAppDir, scanFile)) {
1687 reparseFlags = PackageParser.PARSE_IS_SYSTEM
1688 | PackageParser.PARSE_IS_SYSTEM_DIR
1689 | PackageParser.PARSE_IS_PRIVILEGED;
1690 } else if (FileUtils.contains(systemAppDir, scanFile)) {
1691 reparseFlags = PackageParser.PARSE_IS_SYSTEM
1692 | PackageParser.PARSE_IS_SYSTEM_DIR;
1693 } else if (FileUtils.contains(vendorAppDir, scanFile)) {
1694 reparseFlags = PackageParser.PARSE_IS_SYSTEM
1695 | PackageParser.PARSE_IS_SYSTEM_DIR;
1696 } else if (FileUtils.contains(oemAppDir, scanFile)) {
1697 reparseFlags = PackageParser.PARSE_IS_SYSTEM
1698 | PackageParser.PARSE_IS_SYSTEM_DIR;
1700 Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
1704 mSettings.enableSystemPackageLPw(packageName);
1707 scanPackageLI(scanFile, reparseFlags, scanFlags, 0, null);
1708 } catch (PackageManagerException e) {
1709 Slog.e(TAG, "Failed to parse original system package: "
1716 // Now that we know all of the shared libraries, update all clients to have
1717 // the correct library paths.
1718 updateAllSharedLibrariesLPw();
1720 for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
1721 // NOTE: We ignore potential failures here during a system scan (like
1722 // the rest of the commands above) because there's precious little we
1723 // can do about it. A settings error is reported, though.
1724 adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
1725 false /* force dexopt */, false /* defer dexopt */);
1728 // Now that we know all the packages we are keeping,
1729 // read and update their last usage times.
1730 mPackageUsage.readLP();
1732 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
1733 SystemClock.uptimeMillis());
1734 Slog.i(TAG, "Time to scan packages: "
1735 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1738 // If the platform SDK has changed since the last time we booted,
1739 // we need to re-grant app permission to catch any new ones that
1740 // appear. This is really a hack, and means that apps can in some
1741 // cases get permissions that the user didn't initially explicitly
1742 // allow... it would be nice to have some better way to handle
1744 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1746 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1747 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1748 + "; regranting permissions for internal storage");
1749 mSettings.mInternalSdkPlatform = mSdkVersion;
1751 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
1752 | (regrantPermissions
1753 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
1756 // If this is the first boot, and it is a normal boot, then
1757 // we need to initialize the default preferred apps.
1758 if (!mRestoredSettings && !onlyCore) {
1759 mSettings.readDefaultPreferredAppsLPw(this, 0);
1762 // If this is first boot after an OTA, and a normal boot, then
1763 // we need to clear code cache directories.
1764 mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint);
1765 if (mIsUpgrade && !onlyCore) {
1766 Slog.i(TAG, "Build fingerprint changed; clearing code caches");
1767 for (String pkgName : mSettings.mPackages.keySet()) {
1768 deleteCodeCacheDirsLI(pkgName);
1770 mSettings.mFingerprint = Build.FINGERPRINT;
1773 // All the changes are done during package scanning.
1774 mSettings.updateInternalDatabaseVersion();
1776 // can downgrade to reader
1777 mSettings.writeLPr();
1779 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
1780 SystemClock.uptimeMillis());
1783 mRequiredVerifierPackage = getRequiredVerifierLPr();
1784 } // synchronized (mPackages)
1785 } // synchronized (mInstallLock)
1787 mInstallerService = new PackageInstallerService(context, this, mAppInstallDir);
1789 // Now after opening every single application zip, make sure they
1790 // are all flushed. Not really needed, but keeps things nice and
1792 Runtime.getRuntime().gc();
1796 public boolean isFirstBoot() {
1797 return !mRestoredSettings;
1801 public boolean isOnlyCoreApps() {
1806 public boolean isUpgrade() {
1810 private String getRequiredVerifierLPr() {
1811 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1812 final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
1813 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
1815 String requiredVerifier = null;
1817 final int N = receivers.size();
1818 for (int i = 0; i < N; i++) {
1819 final ResolveInfo info = receivers.get(i);
1821 if (info.activityInfo == null) {
1825 final String packageName = info.activityInfo.packageName;
1827 final PackageSetting ps = mSettings.mPackages.get(packageName);
1832 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1833 if (!gp.grantedPermissions
1834 .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
1838 if (requiredVerifier != null) {
1839 throw new RuntimeException("There can be only one required verifier");
1842 requiredVerifier = packageName;
1845 return requiredVerifier;
1849 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1850 throws RemoteException {
1852 return super.onTransact(code, data, reply, flags);
1853 } catch (RuntimeException e) {
1854 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
1855 Slog.wtf(TAG, "Package Manager Crash", e);
1861 void cleanupInstallFailedPackage(PackageSetting ps) {
1862 logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + ps.name);
1864 removeDataDirsLI(ps.name);
1865 if (ps.codePath != null) {
1866 if (ps.codePath.isDirectory()) {
1867 FileUtils.deleteContents(ps.codePath);
1869 ps.codePath.delete();
1871 if (ps.resourcePath != null && !ps.resourcePath.equals(ps.codePath)) {
1872 if (ps.resourcePath.isDirectory()) {
1873 FileUtils.deleteContents(ps.resourcePath);
1875 ps.resourcePath.delete();
1877 mSettings.removePackageLPw(ps.name);
1880 static int[] appendInts(int[] cur, int[] add) {
1881 if (add == null) return cur;
1882 if (cur == null) return add;
1883 final int N = add.length;
1884 for (int i=0; i<N; i++) {
1885 cur = appendInt(cur, add[i]);
1890 static int[] removeInts(int[] cur, int[] rem) {
1891 if (rem == null) return cur;
1892 if (cur == null) return cur;
1893 final int N = rem.length;
1894 for (int i=0; i<N; i++) {
1895 cur = removeInt(cur, rem[i]);
1900 PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
1901 if (!sUserManager.exists(userId)) return null;
1902 final PackageSetting ps = (PackageSetting) p.mExtras;
1906 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1907 final PackageUserState state = ps.readUserState(userId);
1908 return PackageParser.generatePackageInfo(p, gp.gids, flags,
1909 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
1914 public boolean isPackageAvailable(String packageName, int userId) {
1915 if (!sUserManager.exists(userId)) return false;
1916 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available");
1917 synchronized (mPackages) {
1918 PackageParser.Package p = mPackages.get(packageName);
1920 final PackageSetting ps = (PackageSetting) p.mExtras;
1922 final PackageUserState state = ps.readUserState(userId);
1923 if (state != null) {
1924 return PackageParser.isAvailable(state);
1933 public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
1934 if (!sUserManager.exists(userId)) return null;
1935 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package info");
1937 synchronized (mPackages) {
1938 PackageParser.Package p = mPackages.get(packageName);
1939 if (DEBUG_PACKAGE_INFO)
1940 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
1942 return generatePackageInfo(p, flags, userId);
1944 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1945 return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
1952 public String[] currentToCanonicalPackageNames(String[] names) {
1953 String[] out = new String[names.length];
1955 synchronized (mPackages) {
1956 for (int i=names.length-1; i>=0; i--) {
1957 PackageSetting ps = mSettings.mPackages.get(names[i]);
1958 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1965 public String[] canonicalToCurrentPackageNames(String[] names) {
1966 String[] out = new String[names.length];
1968 synchronized (mPackages) {
1969 for (int i=names.length-1; i>=0; i--) {
1970 String cur = mSettings.mRenamedPackages.get(names[i]);
1971 out[i] = cur != null ? cur : names[i];
1978 public int getPackageUid(String packageName, int userId) {
1979 if (!sUserManager.exists(userId)) return -1;
1980 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid");
1982 synchronized (mPackages) {
1983 PackageParser.Package p = mPackages.get(packageName);
1985 return UserHandle.getUid(userId, p.applicationInfo.uid);
1987 PackageSetting ps = mSettings.mPackages.get(packageName);
1988 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1992 return p != null ? UserHandle.getUid(userId, p.applicationInfo.uid) : -1;
1997 public int[] getPackageGids(String packageName) {
1999 synchronized (mPackages) {
2000 PackageParser.Package p = mPackages.get(packageName);
2001 if (DEBUG_PACKAGE_INFO)
2002 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
2004 final PackageSetting ps = (PackageSetting)p.mExtras;
2005 return ps.getGids();
2008 // stupid thing to indicate an error.
2012 static final PermissionInfo generatePermissionInfo(
2013 BasePermission bp, int flags) {
2014 if (bp.perm != null) {
2015 return PackageParser.generatePermissionInfo(bp.perm, flags);
2017 PermissionInfo pi = new PermissionInfo();
2019 pi.packageName = bp.sourcePackage;
2020 pi.nonLocalizedLabel = bp.name;
2021 pi.protectionLevel = bp.protectionLevel;
2026 public PermissionInfo getPermissionInfo(String name, int flags) {
2028 synchronized (mPackages) {
2029 final BasePermission p = mSettings.mPermissions.get(name);
2031 return generatePermissionInfo(p, flags);
2038 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
2040 synchronized (mPackages) {
2041 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
2042 for (BasePermission p : mSettings.mPermissions.values()) {
2043 if (group == null) {
2044 if (p.perm == null || p.perm.info.group == null) {
2045 out.add(generatePermissionInfo(p, flags));
2048 if (p.perm != null && group.equals(p.perm.info.group)) {
2049 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
2054 if (out.size() > 0) {
2057 return mPermissionGroups.containsKey(group) ? out : null;
2062 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
2064 synchronized (mPackages) {
2065 return PackageParser.generatePermissionGroupInfo(
2066 mPermissionGroups.get(name), flags);
2071 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
2073 synchronized (mPackages) {
2074 final int N = mPermissionGroups.size();
2075 ArrayList<PermissionGroupInfo> out
2076 = new ArrayList<PermissionGroupInfo>(N);
2077 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
2078 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
2084 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
2086 if (!sUserManager.exists(userId)) return null;
2087 PackageSetting ps = mSettings.mPackages.get(packageName);
2089 if (ps.pkg == null) {
2090 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName,
2092 if (pInfo != null) {
2093 return pInfo.applicationInfo;
2097 return PackageParser.generateApplicationInfo(ps.pkg, flags,
2098 ps.readUserState(userId), userId);
2103 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
2105 if (!sUserManager.exists(userId)) return null;
2106 PackageSetting ps = mSettings.mPackages.get(packageName);
2108 PackageParser.Package pkg = ps.pkg;
2110 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
2113 // Only data remains, so we aren't worried about code paths
2114 pkg = new PackageParser.Package(packageName);
2115 pkg.applicationInfo.packageName = packageName;
2116 pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
2117 pkg.applicationInfo.dataDir =
2118 getDataPathForPackage(packageName, 0).getPath();
2119 pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;
2120 pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;
2122 return generatePackageInfo(pkg, flags, userId);
2128 public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
2129 if (!sUserManager.exists(userId)) return null;
2130 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info");
2132 synchronized (mPackages) {
2133 PackageParser.Package p = mPackages.get(packageName);
2134 if (DEBUG_PACKAGE_INFO) Log.v(
2135 TAG, "getApplicationInfo " + packageName
2138 PackageSetting ps = mSettings.mPackages.get(packageName);
2139 if (ps == null) return null;
2140 // Note: isEnabledLP() does not apply here - always return info
2141 return PackageParser.generateApplicationInfo(
2142 p, flags, ps.readUserState(userId), userId);
2144 if ("android".equals(packageName)||"system".equals(packageName)) {
2145 return mAndroidApplication;
2147 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2148 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
2156 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
2157 mContext.enforceCallingOrSelfPermission(
2158 android.Manifest.permission.CLEAR_APP_CACHE, null);
2159 // Queue up an async operation since clearing cache may take a little while.
2160 mHandler.post(new Runnable() {
2162 mHandler.removeCallbacks(this);
2164 synchronized (mInstallLock) {
2165 retCode = mInstaller.freeCache(freeStorageSize);
2167 Slog.w(TAG, "Couldn't clear application caches");
2170 if (observer != null) {
2172 observer.onRemoveCompleted(null, (retCode >= 0));
2173 } catch (RemoteException e) {
2174 Slog.w(TAG, "RemoveException when invoking call back");
2182 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
2183 mContext.enforceCallingOrSelfPermission(
2184 android.Manifest.permission.CLEAR_APP_CACHE, null);
2185 // Queue up an async operation since clearing cache may take a little while.
2186 mHandler.post(new Runnable() {
2188 mHandler.removeCallbacks(this);
2190 synchronized (mInstallLock) {
2191 retCode = mInstaller.freeCache(freeStorageSize);
2193 Slog.w(TAG, "Couldn't clear application caches");
2198 // Callback via pending intent
2199 int code = (retCode >= 0) ? 1 : 0;
2200 pi.sendIntent(null, code, null,
2202 } catch (SendIntentException e1) {
2203 Slog.i(TAG, "Failed to send pending intent");
2210 void freeStorage(long freeStorageSize) throws IOException {
2211 synchronized (mInstallLock) {
2212 if (mInstaller.freeCache(freeStorageSize) < 0) {
2213 throw new IOException("Failed to free enough space");
2219 public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
2220 if (!sUserManager.exists(userId)) return null;
2221 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info");
2222 synchronized (mPackages) {
2223 PackageParser.Activity a = mActivities.mActivities.get(component);
2225 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
2226 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
2227 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2228 if (ps == null) return null;
2229 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
2232 if (mResolveComponentName.equals(component)) {
2233 return PackageParser.generateActivityInfo(mResolveActivity, flags,
2234 new PackageUserState(), userId);
2241 public boolean activitySupportsIntent(ComponentName component, Intent intent,
2242 String resolvedType) {
2243 synchronized (mPackages) {
2244 PackageParser.Activity a = mActivities.mActivities.get(component);
2248 for (int i=0; i<a.intents.size(); i++) {
2249 if (a.intents.get(i).match(intent.getAction(), resolvedType, intent.getScheme(),
2250 intent.getData(), intent.getCategories(), TAG) >= 0) {
2259 public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
2260 if (!sUserManager.exists(userId)) return null;
2261 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info");
2262 synchronized (mPackages) {
2263 PackageParser.Activity a = mReceivers.mActivities.get(component);
2264 if (DEBUG_PACKAGE_INFO) Log.v(
2265 TAG, "getReceiverInfo " + component + ": " + a);
2266 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
2267 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2268 if (ps == null) return null;
2269 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
2277 public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
2278 if (!sUserManager.exists(userId)) return null;
2279 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info");
2280 synchronized (mPackages) {
2281 PackageParser.Service s = mServices.mServices.get(component);
2282 if (DEBUG_PACKAGE_INFO) Log.v(
2283 TAG, "getServiceInfo " + component + ": " + s);
2284 if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
2285 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2286 if (ps == null) return null;
2287 return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
2295 public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
2296 if (!sUserManager.exists(userId)) return null;
2297 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info");
2298 synchronized (mPackages) {
2299 PackageParser.Provider p = mProviders.mProviders.get(component);
2300 if (DEBUG_PACKAGE_INFO) Log.v(
2301 TAG, "getProviderInfo " + component + ": " + p);
2302 if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
2303 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2304 if (ps == null) return null;
2305 return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
2313 public String[] getSystemSharedLibraryNames() {
2315 synchronized (mPackages) {
2316 libSet = mSharedLibraries.keySet();
2317 int size = libSet.size();
2319 String[] libs = new String[size];
2320 libSet.toArray(libs);
2328 public FeatureInfo[] getSystemAvailableFeatures() {
2329 Collection<FeatureInfo> featSet;
2330 synchronized (mPackages) {
2331 featSet = mAvailableFeatures.values();
2332 int size = featSet.size();
2334 FeatureInfo[] features = new FeatureInfo[size+1];
2335 featSet.toArray(features);
2336 FeatureInfo fi = new FeatureInfo();
2337 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
2338 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2339 features[size] = fi;
2347 public boolean hasSystemFeature(String name) {
2348 synchronized (mPackages) {
2349 return mAvailableFeatures.containsKey(name);
2353 private void checkValidCaller(int uid, int userId) {
2354 if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
2357 throw new SecurityException("Caller uid=" + uid
2358 + " is not privileged to communicate with user=" + userId);
2362 public int checkPermission(String permName, String pkgName) {
2363 synchronized (mPackages) {
2364 PackageParser.Package p = mPackages.get(pkgName);
2365 if (p != null && p.mExtras != null) {
2366 PackageSetting ps = (PackageSetting)p.mExtras;
2367 if (ps.sharedUser != null) {
2368 if (ps.sharedUser.grantedPermissions.contains(permName)) {
2369 return PackageManager.PERMISSION_GRANTED;
2371 } else if (ps.grantedPermissions.contains(permName)) {
2372 return PackageManager.PERMISSION_GRANTED;
2376 return PackageManager.PERMISSION_DENIED;
2380 public int checkUidPermission(String permName, int uid) {
2381 synchronized (mPackages) {
2382 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
2384 GrantedPermissions gp = (GrantedPermissions)obj;
2385 if (gp.grantedPermissions.contains(permName)) {
2386 return PackageManager.PERMISSION_GRANTED;
2389 ArraySet<String> perms = mSystemPermissions.get(uid);
2390 if (perms != null && perms.contains(permName)) {
2391 return PackageManager.PERMISSION_GRANTED;
2395 return PackageManager.PERMISSION_DENIED;
2399 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
2400 * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
2401 * @param checkShell TODO(yamasani):
2402 * @param message the message to log on security exception
2404 void enforceCrossUserPermission(int callingUid, int userId, boolean requireFullPermission,
2405 boolean checkShell, String message) {
2407 throw new IllegalArgumentException("Invalid userId " + userId);
2410 enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
2412 if (userId == UserHandle.getUserId(callingUid)) return;
2413 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
2414 if (requireFullPermission) {
2415 mContext.enforceCallingOrSelfPermission(
2416 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
2419 mContext.enforceCallingOrSelfPermission(
2420 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
2421 } catch (SecurityException se) {
2422 mContext.enforceCallingOrSelfPermission(
2423 android.Manifest.permission.INTERACT_ACROSS_USERS, message);
2429 void enforceShellRestriction(String restriction, int callingUid, int userHandle) {
2430 if (callingUid == Process.SHELL_UID) {
2432 && sUserManager.hasUserRestriction(restriction, userHandle)) {
2433 throw new SecurityException("Shell does not have permission to access user "
2435 } else if (userHandle < 0) {
2436 Slog.e(TAG, "Unable to check shell permission for user " + userHandle + "\n\t"
2437 + Debug.getCallers(3));
2442 private BasePermission findPermissionTreeLP(String permName) {
2443 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
2444 if (permName.startsWith(bp.name) &&
2445 permName.length() > bp.name.length() &&
2446 permName.charAt(bp.name.length()) == '.') {
2453 private BasePermission checkPermissionTreeLP(String permName) {
2454 if (permName != null) {
2455 BasePermission bp = findPermissionTreeLP(permName);
2457 if (bp.uid == UserHandle.getAppId(Binder.getCallingUid())) {
2460 throw new SecurityException("Calling uid "
2461 + Binder.getCallingUid()
2462 + " is not allowed to add to permission tree "
2463 + bp.name + " owned by uid " + bp.uid);
2466 throw new SecurityException("No permission tree found for " + permName);
2469 static boolean compareStrings(CharSequence s1, CharSequence s2) {
2476 if (s1.getClass() != s2.getClass()) {
2479 return s1.equals(s2);
2482 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
2483 if (pi1.icon != pi2.icon) return false;
2484 if (pi1.logo != pi2.logo) return false;
2485 if (pi1.protectionLevel != pi2.protectionLevel) return false;
2486 if (!compareStrings(pi1.name, pi2.name)) return false;
2487 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
2488 // We'll take care of setting this one.
2489 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
2490 // These are not currently stored in settings.
2491 //if (!compareStrings(pi1.group, pi2.group)) return false;
2492 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
2493 //if (pi1.labelRes != pi2.labelRes) return false;
2494 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
2498 int permissionInfoFootprint(PermissionInfo info) {
2499 int size = info.name.length();
2500 if (info.nonLocalizedLabel != null) size += info.nonLocalizedLabel.length();
2501 if (info.nonLocalizedDescription != null) size += info.nonLocalizedDescription.length();
2505 int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
2507 for (BasePermission perm : mSettings.mPermissions.values()) {
2508 if (perm.uid == tree.uid) {
2509 size += perm.name.length() + permissionInfoFootprint(perm.perm.info);
2515 void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
2516 // We calculate the max size of permissions defined by this uid and throw
2517 // if that plus the size of 'info' would exceed our stated maximum.
2518 if (tree.uid != Process.SYSTEM_UID) {
2519 final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
2520 if (curTreeSize + permissionInfoFootprint(info) > MAX_PERMISSION_TREE_FOOTPRINT) {
2521 throw new SecurityException("Permission tree size cap exceeded");
2526 boolean addPermissionLocked(PermissionInfo info, boolean async) {
2527 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
2528 throw new SecurityException("Label must be specified in permission");
2530 BasePermission tree = checkPermissionTreeLP(info.name);
2531 BasePermission bp = mSettings.mPermissions.get(info.name);
2532 boolean added = bp == null;
2533 boolean changed = true;
2534 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
2536 enforcePermissionCapLocked(info, tree);
2537 bp = new BasePermission(info.name, tree.sourcePackage,
2538 BasePermission.TYPE_DYNAMIC);
2539 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
2540 throw new SecurityException(
2541 "Not allowed to modify non-dynamic permission "
2544 if (bp.protectionLevel == fixedLevel
2545 && bp.perm.owner.equals(tree.perm.owner)
2546 && bp.uid == tree.uid
2547 && comparePermissionInfos(bp.perm.info, info)) {
2551 bp.protectionLevel = fixedLevel;
2552 info = new PermissionInfo(info);
2553 info.protectionLevel = fixedLevel;
2554 bp.perm = new PackageParser.Permission(tree.perm.owner, info);
2555 bp.perm.info.packageName = tree.perm.info.packageName;
2558 mSettings.mPermissions.put(info.name, bp);
2562 mSettings.writeLPr();
2564 scheduleWriteSettingsLocked();
2571 public boolean addPermission(PermissionInfo info) {
2572 synchronized (mPackages) {
2573 return addPermissionLocked(info, false);
2578 public boolean addPermissionAsync(PermissionInfo info) {
2579 synchronized (mPackages) {
2580 return addPermissionLocked(info, true);
2585 public void removePermission(String name) {
2586 synchronized (mPackages) {
2587 checkPermissionTreeLP(name);
2588 BasePermission bp = mSettings.mPermissions.get(name);
2590 if (bp.type != BasePermission.TYPE_DYNAMIC) {
2591 throw new SecurityException(
2592 "Not allowed to modify non-dynamic permission "
2595 mSettings.mPermissions.remove(name);
2596 mSettings.writeLPr();
2601 private static void checkGrantRevokePermissions(PackageParser.Package pkg, BasePermission bp) {
2602 int index = pkg.requestedPermissions.indexOf(bp.name);
2604 throw new SecurityException("Package " + pkg.packageName
2605 + " has not requested permission " + bp.name);
2608 ((bp.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE)
2609 == PermissionInfo.PROTECTION_NORMAL);
2610 boolean isDangerous =
2611 ((bp.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE)
2612 == PermissionInfo.PROTECTION_DANGEROUS);
2613 boolean isDevelopment =
2614 ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
2616 if (!isNormal && !isDangerous && !isDevelopment) {
2617 throw new SecurityException("Permission " + bp.name
2618 + " is not a changeable permission type");
2621 if (isNormal || isDangerous) {
2622 if (pkg.requestedPermissionsRequired.get(index)) {
2623 throw new SecurityException("Can't change " + bp.name
2624 + ". It is required by the application");
2630 public void grantPermission(String packageName, String permissionName) {
2631 mContext.enforceCallingOrSelfPermission(
2632 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2633 synchronized (mPackages) {
2634 final PackageParser.Package pkg = mPackages.get(packageName);
2636 throw new IllegalArgumentException("Unknown package: " + packageName);
2638 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2640 throw new IllegalArgumentException("Unknown permission: " + permissionName);
2643 checkGrantRevokePermissions(pkg, bp);
2645 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2649 final GrantedPermissions gp = (ps.sharedUser != null) ? ps.sharedUser : ps;
2650 if (gp.grantedPermissions.add(permissionName)) {
2652 gp.gids = appendInts(gp.gids, bp.gids);
2654 mSettings.writeLPr();
2660 public void revokePermission(String packageName, String permissionName) {
2661 int changedAppId = -1;
2663 synchronized (mPackages) {
2664 final PackageParser.Package pkg = mPackages.get(packageName);
2666 throw new IllegalArgumentException("Unknown package: " + packageName);
2668 if (pkg.applicationInfo.uid != Binder.getCallingUid()) {
2669 mContext.enforceCallingOrSelfPermission(
2670 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2672 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2674 throw new IllegalArgumentException("Unknown permission: " + permissionName);
2677 checkGrantRevokePermissions(pkg, bp);
2679 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2683 final GrantedPermissions gp = (ps.sharedUser != null) ? ps.sharedUser : ps;
2684 if (gp.grantedPermissions.remove(permissionName)) {
2685 gp.grantedPermissions.remove(permissionName);
2687 gp.gids = removeInts(gp.gids, bp.gids);
2689 mSettings.writeLPr();
2690 changedAppId = ps.appId;
2694 if (changedAppId >= 0) {
2695 // We changed the perm on someone, kill its processes.
2696 IActivityManager am = ActivityManagerNative.getDefault();
2698 final int callingUserId = UserHandle.getCallingUserId();
2699 final long ident = Binder.clearCallingIdentity();
2701 //XXX we should only revoke for the calling user's app permissions,
2702 // but for now we impact all users.
2703 //am.killUid(UserHandle.getUid(callingUserId, changedAppId),
2704 // "revoke " + permissionName);
2705 int[] users = sUserManager.getUserIds();
2706 for (int user : users) {
2707 am.killUid(UserHandle.getUid(user, changedAppId),
2708 "revoke " + permissionName);
2710 } catch (RemoteException e) {
2712 Binder.restoreCallingIdentity(ident);
2719 public boolean isProtectedBroadcast(String actionName) {
2720 synchronized (mPackages) {
2721 return mProtectedBroadcasts.contains(actionName);
2726 public int checkSignatures(String pkg1, String pkg2) {
2727 synchronized (mPackages) {
2728 final PackageParser.Package p1 = mPackages.get(pkg1);
2729 final PackageParser.Package p2 = mPackages.get(pkg2);
2730 if (p1 == null || p1.mExtras == null
2731 || p2 == null || p2.mExtras == null) {
2732 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2734 return compareSignatures(p1.mSignatures, p2.mSignatures);
2739 public int checkUidSignatures(int uid1, int uid2) {
2740 // Map to base uids.
2741 uid1 = UserHandle.getAppId(uid1);
2742 uid2 = UserHandle.getAppId(uid2);
2744 synchronized (mPackages) {
2747 Object obj = mSettings.getUserIdLPr(uid1);
2749 if (obj instanceof SharedUserSetting) {
2750 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
2751 } else if (obj instanceof PackageSetting) {
2752 s1 = ((PackageSetting)obj).signatures.mSignatures;
2754 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2757 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2759 obj = mSettings.getUserIdLPr(uid2);
2761 if (obj instanceof SharedUserSetting) {
2762 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
2763 } else if (obj instanceof PackageSetting) {
2764 s2 = ((PackageSetting)obj).signatures.mSignatures;
2766 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2769 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2771 return compareSignatures(s1, s2);
2776 * Compares two sets of signatures. Returns:
2778 * {@link PackageManager#SIGNATURE_NEITHER_SIGNED}: if both signature sets are null,
2780 * {@link PackageManager#SIGNATURE_FIRST_NOT_SIGNED}: if the first signature set is null,
2782 * {@link PackageManager#SIGNATURE_SECOND_NOT_SIGNED}: if the second signature set is null,
2784 * {@link PackageManager#SIGNATURE_MATCH}: if the two signature sets are identical,
2786 * {@link PackageManager#SIGNATURE_NO_MATCH}: if the two signature sets differ.
2788 static int compareSignatures(Signature[] s1, Signature[] s2) {
2791 ? PackageManager.SIGNATURE_NEITHER_SIGNED
2792 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
2796 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
2799 if (s1.length != s2.length) {
2800 return PackageManager.SIGNATURE_NO_MATCH;
2803 // Since both signature sets are of size 1, we can compare without HashSets.
2804 if (s1.length == 1) {
2805 return s1[0].equals(s2[0]) ?
2806 PackageManager.SIGNATURE_MATCH :
2807 PackageManager.SIGNATURE_NO_MATCH;
2810 ArraySet<Signature> set1 = new ArraySet<Signature>();
2811 for (Signature sig : s1) {
2814 ArraySet<Signature> set2 = new ArraySet<Signature>();
2815 for (Signature sig : s2) {
2818 // Make sure s2 contains all signatures in s1.
2819 if (set1.equals(set2)) {
2820 return PackageManager.SIGNATURE_MATCH;
2822 return PackageManager.SIGNATURE_NO_MATCH;
2826 * If the database version for this type of package (internal storage or
2827 * external storage) is less than the version where package signatures
2828 * were updated, return true.
2830 private boolean isCompatSignatureUpdateNeeded(PackageParser.Package scannedPkg) {
2831 return (isExternal(scannedPkg) && mSettings.isExternalDatabaseVersionOlderThan(
2832 DatabaseVersion.SIGNATURE_END_ENTITY))
2833 || (!isExternal(scannedPkg) && mSettings.isInternalDatabaseVersionOlderThan(
2834 DatabaseVersion.SIGNATURE_END_ENTITY));
2838 * Used for backward compatibility to make sure any packages with
2839 * certificate chains get upgraded to the new style. {@code existingSigs}
2840 * will be in the old format (since they were stored on disk from before the
2841 * system upgrade) and {@code scannedSigs} will be in the newer format.
2843 private int compareSignaturesCompat(PackageSignatures existingSigs,
2844 PackageParser.Package scannedPkg) {
2845 if (!isCompatSignatureUpdateNeeded(scannedPkg)) {
2846 return PackageManager.SIGNATURE_NO_MATCH;
2849 ArraySet<Signature> existingSet = new ArraySet<Signature>();
2850 for (Signature sig : existingSigs.mSignatures) {
2851 existingSet.add(sig);
2853 ArraySet<Signature> scannedCompatSet = new ArraySet<Signature>();
2854 for (Signature sig : scannedPkg.mSignatures) {
2856 Signature[] chainSignatures = sig.getChainSignatures();
2857 for (Signature chainSig : chainSignatures) {
2858 scannedCompatSet.add(chainSig);
2860 } catch (CertificateEncodingException e) {
2861 scannedCompatSet.add(sig);
2865 * Make sure the expanded scanned set contains all signatures in the
2868 if (scannedCompatSet.equals(existingSet)) {
2869 // Migrate the old signatures to the new scheme.
2870 existingSigs.assignSignatures(scannedPkg.mSignatures);
2871 // The new KeySets will be re-added later in the scanning process.
2872 synchronized (mPackages) {
2873 mSettings.mKeySetManagerService.removeAppKeySetDataLPw(scannedPkg.packageName);
2875 return PackageManager.SIGNATURE_MATCH;
2877 return PackageManager.SIGNATURE_NO_MATCH;
2881 public String[] getPackagesForUid(int uid) {
2882 uid = UserHandle.getAppId(uid);
2884 synchronized (mPackages) {
2885 Object obj = mSettings.getUserIdLPr(uid);
2886 if (obj instanceof SharedUserSetting) {
2887 final SharedUserSetting sus = (SharedUserSetting) obj;
2888 final int N = sus.packages.size();
2889 final String[] res = new String[N];
2890 final Iterator<PackageSetting> it = sus.packages.iterator();
2892 while (it.hasNext()) {
2893 res[i++] = it.next().name;
2896 } else if (obj instanceof PackageSetting) {
2897 final PackageSetting ps = (PackageSetting) obj;
2898 return new String[] { ps.name };
2905 public String getNameForUid(int uid) {
2907 synchronized (mPackages) {
2908 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
2909 if (obj instanceof SharedUserSetting) {
2910 final SharedUserSetting sus = (SharedUserSetting) obj;
2911 return sus.name + ":" + sus.userId;
2912 } else if (obj instanceof PackageSetting) {
2913 final PackageSetting ps = (PackageSetting) obj;
2921 public int getUidForSharedUser(String sharedUserName) {
2922 if(sharedUserName == null) {
2926 synchronized (mPackages) {
2927 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
2936 public int getFlagsForUid(int uid) {
2937 synchronized (mPackages) {
2938 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
2939 if (obj instanceof SharedUserSetting) {
2940 final SharedUserSetting sus = (SharedUserSetting) obj;
2941 return sus.pkgFlags;
2942 } else if (obj instanceof PackageSetting) {
2943 final PackageSetting ps = (PackageSetting) obj;
2951 public boolean isUidPrivileged(int uid) {
2952 uid = UserHandle.getAppId(uid);
2954 synchronized (mPackages) {
2955 Object obj = mSettings.getUserIdLPr(uid);
2956 if (obj instanceof SharedUserSetting) {
2957 final SharedUserSetting sus = (SharedUserSetting) obj;
2958 final Iterator<PackageSetting> it = sus.packages.iterator();
2959 while (it.hasNext()) {
2960 if (it.next().isPrivileged()) {
2964 } else if (obj instanceof PackageSetting) {
2965 final PackageSetting ps = (PackageSetting) obj;
2966 return ps.isPrivileged();
2973 public String[] getAppOpPermissionPackages(String permissionName) {
2974 synchronized (mPackages) {
2975 ArraySet<String> pkgs = mAppOpPermissionPackages.get(permissionName);
2979 return pkgs.toArray(new String[pkgs.size()]);
2984 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
2985 int flags, int userId) {
2986 if (!sUserManager.exists(userId)) return null;
2987 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
2988 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2989 return chooseBestActivity(intent, resolvedType, flags, query, userId);
2993 public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
2994 IntentFilter filter, int match, ComponentName activity) {
2995 final int userId = UserHandle.getCallingUserId();
2996 if (DEBUG_PREFERRED) {
2997 Log.v(TAG, "setLastChosenActivity intent=" + intent
2998 + " resolvedType=" + resolvedType
3000 + " filter=" + filter
3002 + " activity=" + activity);
3003 filter.dump(new PrintStreamPrinter(System.out), " ");
3005 intent.setComponent(null);
3006 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
3007 // Find any earlier preferred or last chosen entries and nuke them
3008 findPreferredActivity(intent, resolvedType,
3009 flags, query, 0, false, true, false, userId);
3010 // Add the new activity as the last chosen for this filter
3011 addPreferredActivityInternal(filter, match, null, activity, false, userId,
3012 "Setting last chosen");
3016 public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) {
3017 final int userId = UserHandle.getCallingUserId();
3018 if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
3019 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
3020 return findPreferredActivity(intent, resolvedType, flags, query, 0,
3021 false, false, false, userId);
3024 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
3025 int flags, List<ResolveInfo> query, int userId) {
3026 if (query != null) {
3027 final int N = query.size();
3029 return query.get(0);
3031 final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
3032 // If there is more than one activity with the same priority,
3033 // then let the user decide between them.
3034 ResolveInfo r0 = query.get(0);
3035 ResolveInfo r1 = query.get(1);
3036 if (DEBUG_INTENT_MATCHING || debug) {
3037 Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
3038 + r1.activityInfo.name + "=" + r1.priority);
3040 // If the first activity has a higher priority, or a different
3041 // default, then it is always desireable to pick it.
3042 if (r0.priority != r1.priority
3043 || r0.preferredOrder != r1.preferredOrder
3044 || r0.isDefault != r1.isDefault) {
3045 return query.get(0);
3047 // If we have saved a preference for a preferred activity for
3048 // this Intent, use that.
3049 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
3050 flags, query, r0.priority, true, false, debug, userId);
3055 ri = new ResolveInfo(mResolveInfo);
3056 ri.activityInfo = new ActivityInfo(ri.activityInfo);
3057 ri.activityInfo.applicationInfo = new ApplicationInfo(
3058 ri.activityInfo.applicationInfo);
3059 ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
3060 UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
3063 return mResolveInfo;
3069 private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType,
3070 int flags, List<ResolveInfo> query, boolean debug, int userId) {
3071 final int N = query.size();
3072 PersistentPreferredIntentResolver ppir = mSettings.mPersistentPreferredActivities
3074 // Get the list of persistent preferred activities that handle the intent
3075 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for presistent preferred activities...");
3076 List<PersistentPreferredActivity> pprefs = ppir != null
3077 ? ppir.queryIntent(intent, resolvedType,
3078 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
3080 if (pprefs != null && pprefs.size() > 0) {
3081 final int M = pprefs.size();
3082 for (int i=0; i<M; i++) {
3083 final PersistentPreferredActivity ppa = pprefs.get(i);
3084 if (DEBUG_PREFERRED || debug) {
3085 Slog.v(TAG, "Checking PersistentPreferredActivity ds="
3086 + (ppa.countDataSchemes() > 0 ? ppa.getDataScheme(0) : "<none>")
3087 + "\n component=" + ppa.mComponent);
3088 ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
3090 final ActivityInfo ai = getActivityInfo(ppa.mComponent,
3091 flags | PackageManager.GET_DISABLED_COMPONENTS, userId);
3092 if (DEBUG_PREFERRED || debug) {
3093 Slog.v(TAG, "Found persistent preferred activity:");
3095 ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
3097 Slog.v(TAG, " null");
3101 // This previously registered persistent preferred activity
3102 // component is no longer known. Ignore it and do NOT remove it.
3105 for (int j=0; j<N; j++) {
3106 final ResolveInfo ri = query.get(j);
3107 if (!ri.activityInfo.applicationInfo.packageName
3108 .equals(ai.applicationInfo.packageName)) {
3111 if (!ri.activityInfo.name.equals(ai.name)) {
3114 // Found a persistent preference that can handle the intent.
3115 if (DEBUG_PREFERRED || debug) {
3116 Slog.v(TAG, "Returning persistent preferred activity: " +
3117 ri.activityInfo.packageName + "/" + ri.activityInfo.name);
3126 ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
3127 List<ResolveInfo> query, int priority, boolean always,
3128 boolean removeMatches, boolean debug, int userId) {
3129 if (!sUserManager.exists(userId)) return null;
3131 synchronized (mPackages) {
3132 if (intent.getSelector() != null) {
3133 intent = intent.getSelector();
3135 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
3137 // Try to find a matching persistent preferred activity.
3138 ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query,
3141 // If a persistent preferred activity matched, use it.
3146 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
3147 // Get the list of preferred activities that handle the intent
3148 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
3149 List<PreferredActivity> prefs = pir != null
3150 ? pir.queryIntent(intent, resolvedType,
3151 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
3153 if (prefs != null && prefs.size() > 0) {
3154 boolean changed = false;
3156 // First figure out how good the original match set is.
3157 // We will only allow preferred activities that came
3158 // from the same match quality.
3161 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match...");
3163 final int N = query.size();
3164 for (int j=0; j<N; j++) {
3165 final ResolveInfo ri = query.get(j);
3166 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Match for " + ri.activityInfo
3167 + ": 0x" + Integer.toHexString(match));
3168 if (ri.match > match) {
3173 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Best match: 0x"
3174 + Integer.toHexString(match));
3176 match &= IntentFilter.MATCH_CATEGORY_MASK;
3177 final int M = prefs.size();
3178 for (int i=0; i<M; i++) {
3179 final PreferredActivity pa = prefs.get(i);
3180 if (DEBUG_PREFERRED || debug) {
3181 Slog.v(TAG, "Checking PreferredActivity ds="
3182 + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>")
3183 + "\n component=" + pa.mPref.mComponent);
3184 pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
3186 if (pa.mPref.mMatch != match) {
3187 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping bad match "
3188 + Integer.toHexString(pa.mPref.mMatch));
3191 // If it's not an "always" type preferred activity and that's what we're
3192 // looking for, skip it.
3193 if (always && !pa.mPref.mAlways) {
3194 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry");
3197 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent,
3198 flags | PackageManager.GET_DISABLED_COMPONENTS, userId);
3199 if (DEBUG_PREFERRED || debug) {
3200 Slog.v(TAG, "Found preferred activity:");
3202 ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
3204 Slog.v(TAG, " null");
3208 // This previously registered preferred activity
3209 // component is no longer known. Most likely an update
3210 // to the app was installed and in the new version this
3211 // component no longer exists. Clean it up by removing
3212 // it from the preferred activities list, and skip it.
3213 Slog.w(TAG, "Removing dangling preferred activity: "
3214 + pa.mPref.mComponent);
3215 pir.removeFilter(pa);
3219 for (int j=0; j<N; j++) {
3220 final ResolveInfo ri = query.get(j);
3221 if (!ri.activityInfo.applicationInfo.packageName
3222 .equals(ai.applicationInfo.packageName)) {
3225 if (!ri.activityInfo.name.equals(ai.name)) {
3229 if (removeMatches) {
3230 pir.removeFilter(pa);
3232 if (DEBUG_PREFERRED) {
3233 Slog.v(TAG, "Removing match " + pa.mPref.mComponent);
3238 // Okay we found a previously set preferred or last chosen app.
3239 // If the result set is different from when this
3240 // was created, we need to clear it and re-ask the
3241 // user their preference, if we're looking for an "always" type entry.
3242 if (always && !pa.mPref.sameSet(query, priority)) {
3243 Slog.i(TAG, "Result set changed, dropping preferred activity for "
3244 + intent + " type " + resolvedType);
3245 if (DEBUG_PREFERRED) {
3246 Slog.v(TAG, "Removing preferred activity since set changed "
3247 + pa.mPref.mComponent);
3249 pir.removeFilter(pa);
3250 // Re-add the filter as a "last chosen" entry (!always)
3251 PreferredActivity lastChosen = new PreferredActivity(
3252 pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
3253 pir.addFilter(lastChosen);
3258 // Yay! Either the set matched or we're looking for the last chosen
3259 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: "
3260 + ri.activityInfo.packageName + "/" + ri.activityInfo.name);
3266 if (DEBUG_PREFERRED) {
3267 Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
3269 scheduleWritePackageRestrictionsLocked(userId);
3274 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "No preferred activity to return");
3279 * Returns if intent can be forwarded from the sourceUserId to the targetUserId
3282 public boolean canForwardTo(Intent intent, String resolvedType, int sourceUserId,
3284 mContext.enforceCallingOrSelfPermission(
3285 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
3286 List<CrossProfileIntentFilter> matches =
3287 getMatchingCrossProfileIntentFilters(intent, resolvedType, sourceUserId);
3288 if (matches != null) {
3289 int size = matches.size();
3290 for (int i = 0; i < size; i++) {
3291 if (matches.get(i).getTargetUserId() == targetUserId) return true;
3297 private List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent,
3298 String resolvedType, int userId) {
3299 CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId);
3300 if (resolver != null) {
3301 return resolver.queryIntent(intent, resolvedType, false, userId);
3307 public List<ResolveInfo> queryIntentActivities(Intent intent,
3308 String resolvedType, int flags, int userId) {
3309 if (!sUserManager.exists(userId)) return Collections.emptyList();
3310 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities");
3311 ComponentName comp = intent.getComponent();
3313 if (intent.getSelector() != null) {
3314 intent = intent.getSelector();
3315 comp = intent.getComponent();
3320 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
3321 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
3323 final ResolveInfo ri = new ResolveInfo();
3324 ri.activityInfo = ai;
3331 synchronized (mPackages) {
3332 final String pkgName = intent.getPackage();
3333 if (pkgName == null) {
3334 List<CrossProfileIntentFilter> matchingFilters =
3335 getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
3336 // Check for results that need to skip the current profile.
3337 ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
3338 resolvedType, flags, userId);
3339 if (resolveInfo != null) {
3340 List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
3341 result.add(resolveInfo);
3344 // Check for cross profile results.
3345 resolveInfo = queryCrossProfileIntents(
3346 matchingFilters, intent, resolvedType, flags, userId);
3348 // Check for results in the current profile.
3349 List<ResolveInfo> result = mActivities.queryIntent(
3350 intent, resolvedType, flags, userId);
3351 if (resolveInfo != null) {
3352 result.add(resolveInfo);
3353 Collections.sort(result, mResolvePrioritySorter);
3357 final PackageParser.Package pkg = mPackages.get(pkgName);
3359 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
3360 pkg.activities, userId);
3362 return new ArrayList<ResolveInfo>();
3366 private ResolveInfo querySkipCurrentProfileIntents(
3367 List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
3368 int flags, int sourceUserId) {
3369 if (matchingFilters != null) {
3370 int size = matchingFilters.size();
3371 for (int i = 0; i < size; i ++) {
3372 CrossProfileIntentFilter filter = matchingFilters.get(i);
3373 if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0) {
3374 // Checking if there are activities in the target user that can handle the
3376 ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType,
3377 flags, sourceUserId);
3378 if (resolveInfo != null) {
3387 // Return matching ResolveInfo if any for skip current profile intent filters.
3388 private ResolveInfo queryCrossProfileIntents(
3389 List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
3390 int flags, int sourceUserId) {
3391 if (matchingFilters != null) {
3392 // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and
3393 // match the same intent. For performance reasons, it is better not to
3394 // run queryIntent twice for the same userId
3395 SparseBooleanArray alreadyTriedUserIds = new SparseBooleanArray();
3396 int size = matchingFilters.size();
3397 for (int i = 0; i < size; i++) {
3398 CrossProfileIntentFilter filter = matchingFilters.get(i);
3399 int targetUserId = filter.getTargetUserId();
3400 if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) == 0
3401 && !alreadyTriedUserIds.get(targetUserId)) {
3402 // Checking if there are activities in the target user that can handle the
3404 ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType,
3405 flags, sourceUserId);
3406 if (resolveInfo != null) return resolveInfo;
3407 alreadyTriedUserIds.put(targetUserId, true);
3414 private ResolveInfo checkTargetCanHandle(CrossProfileIntentFilter filter, Intent intent,
3415 String resolvedType, int flags, int sourceUserId) {
3416 List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
3417 resolvedType, flags, filter.getTargetUserId());
3418 if (resultTargetUser != null && !resultTargetUser.isEmpty()) {
3419 return createForwardingResolveInfo(filter, sourceUserId, filter.getTargetUserId());
3424 private ResolveInfo createForwardingResolveInfo(IntentFilter filter,
3425 int sourceUserId, int targetUserId) {
3426 ResolveInfo forwardingResolveInfo = new ResolveInfo();
3428 if (targetUserId == UserHandle.USER_OWNER) {
3429 className = FORWARD_INTENT_TO_USER_OWNER;
3431 className = FORWARD_INTENT_TO_MANAGED_PROFILE;
3433 ComponentName forwardingActivityComponentName = new ComponentName(
3434 mAndroidApplication.packageName, className);
3435 ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
3437 if (targetUserId == UserHandle.USER_OWNER) {
3438 forwardingActivityInfo.showUserIcon = UserHandle.USER_OWNER;
3439 forwardingResolveInfo.noResourceId = true;
3441 forwardingResolveInfo.activityInfo = forwardingActivityInfo;
3442 forwardingResolveInfo.priority = 0;
3443 forwardingResolveInfo.preferredOrder = 0;
3444 forwardingResolveInfo.match = 0;
3445 forwardingResolveInfo.isDefault = true;
3446 forwardingResolveInfo.filter = filter;
3447 forwardingResolveInfo.targetUserId = targetUserId;
3448 return forwardingResolveInfo;
3452 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
3453 Intent[] specifics, String[] specificTypes, Intent intent,
3454 String resolvedType, int flags, int userId) {
3455 if (!sUserManager.exists(userId)) return Collections.emptyList();
3456 enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
3457 false, "query intent activity options");
3458 final String resultsAction = intent.getAction();
3460 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
3461 | PackageManager.GET_RESOLVED_FILTER, userId);
3463 if (DEBUG_INTENT_MATCHING) {
3464 Log.v(TAG, "Query " + intent + ": " + results);
3467 int specificsPos = 0;
3470 // todo: note that the algorithm used here is O(N^2). This
3471 // isn't a problem in our current environment, but if we start running
3472 // into situations where we have more than 5 or 10 matches then this
3473 // should probably be changed to something smarter...
3475 // First we go through and resolve each of the specific items
3476 // that were supplied, taking care of removing any corresponding
3477 // duplicate items in the generic resolve list.
3478 if (specifics != null) {
3479 for (int i=0; i<specifics.length; i++) {
3480 final Intent sintent = specifics[i];
3481 if (sintent == null) {
3485 if (DEBUG_INTENT_MATCHING) {
3486 Log.v(TAG, "Specific #" + i + ": " + sintent);
3489 String action = sintent.getAction();
3490 if (resultsAction != null && resultsAction.equals(action)) {
3491 // If this action was explicitly requested, then don't
3492 // remove things that have it.
3496 ResolveInfo ri = null;
3497 ActivityInfo ai = null;
3499 ComponentName comp = sintent.getComponent();
3503 specificTypes != null ? specificTypes[i] : null,
3508 if (ri == mResolveInfo) {
3509 // ACK! Must do something better with this.
3511 ai = ri.activityInfo;
3512 comp = new ComponentName(ai.applicationInfo.packageName,
3515 ai = getActivityInfo(comp, flags, userId);
3521 // Look for any generic query activities that are duplicates
3522 // of this specific one, and remove them from the results.
3523 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
3526 for (j=specificsPos; j<N; j++) {
3527 ResolveInfo sri = results.get(j);
3528 if ((sri.activityInfo.name.equals(comp.getClassName())
3529 && sri.activityInfo.applicationInfo.packageName.equals(
3530 comp.getPackageName()))
3531 || (action != null && sri.filter.matchAction(action))) {
3533 if (DEBUG_INTENT_MATCHING) Log.v(
3534 TAG, "Removing duplicate item from " + j
3535 + " due to specific " + specificsPos);
3544 // Add this specific item to its proper place.
3546 ri = new ResolveInfo();
3547 ri.activityInfo = ai;
3549 results.add(specificsPos, ri);
3550 ri.specificIndex = i;
3555 // Now we go through the remaining generic results and remove any
3556 // duplicate actions that are found here.
3558 for (int i=specificsPos; i<N-1; i++) {
3559 final ResolveInfo rii = results.get(i);
3560 if (rii.filter == null) {
3564 // Iterate over all of the actions of this result's intent
3565 // filter... typically this should be just one.
3566 final Iterator<String> it = rii.filter.actionsIterator();
3570 while (it.hasNext()) {
3571 final String action = it.next();
3572 if (resultsAction != null && resultsAction.equals(action)) {
3573 // If this action was explicitly requested, then don't
3574 // remove things that have it.
3577 for (int j=i+1; j<N; j++) {
3578 final ResolveInfo rij = results.get(j);
3579 if (rij.filter != null && rij.filter.hasAction(action)) {
3581 if (DEBUG_INTENT_MATCHING) Log.v(
3582 TAG, "Removing duplicate item from " + j
3583 + " due to action " + action + " at " + i);
3590 // If the caller didn't request filter information, drop it now
3591 // so we don't have to marshall/unmarshall it.
3592 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
3597 // Filter out the caller activity if so requested.
3598 if (caller != null) {
3600 for (int i=0; i<N; i++) {
3601 ActivityInfo ainfo = results.get(i).activityInfo;
3602 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
3603 && caller.getClassName().equals(ainfo.name)) {
3610 // If the caller didn't request filter information,
3611 // drop them now so we don't have to
3612 // marshall/unmarshall it.
3613 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
3615 for (int i=0; i<N; i++) {
3616 results.get(i).filter = null;
3620 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
3625 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
3627 if (!sUserManager.exists(userId)) return Collections.emptyList();
3628 ComponentName comp = intent.getComponent();
3630 if (intent.getSelector() != null) {
3631 intent = intent.getSelector();
3632 comp = intent.getComponent();
3636 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
3637 ActivityInfo ai = getReceiverInfo(comp, flags, userId);
3639 ResolveInfo ri = new ResolveInfo();
3640 ri.activityInfo = ai;
3647 synchronized (mPackages) {
3648 String pkgName = intent.getPackage();
3649 if (pkgName == null) {
3650 return mReceivers.queryIntent(intent, resolvedType, flags, userId);
3652 final PackageParser.Package pkg = mPackages.get(pkgName);
3654 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
3662 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
3663 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
3664 if (!sUserManager.exists(userId)) return null;
3665 if (query != null) {
3666 if (query.size() >= 1) {
3667 // If there is more than one service with the same priority,
3668 // just arbitrarily pick the first one.
3669 return query.get(0);
3676 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
3678 if (!sUserManager.exists(userId)) return Collections.emptyList();
3679 ComponentName comp = intent.getComponent();
3681 if (intent.getSelector() != null) {
3682 intent = intent.getSelector();
3683 comp = intent.getComponent();
3687 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
3688 final ServiceInfo si = getServiceInfo(comp, flags, userId);
3690 final ResolveInfo ri = new ResolveInfo();
3691 ri.serviceInfo = si;
3698 synchronized (mPackages) {
3699 String pkgName = intent.getPackage();
3700 if (pkgName == null) {
3701 return mServices.queryIntent(intent, resolvedType, flags, userId);
3703 final PackageParser.Package pkg = mPackages.get(pkgName);
3705 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
3713 public List<ResolveInfo> queryIntentContentProviders(
3714 Intent intent, String resolvedType, int flags, int userId) {
3715 if (!sUserManager.exists(userId)) return Collections.emptyList();
3716 ComponentName comp = intent.getComponent();
3718 if (intent.getSelector() != null) {
3719 intent = intent.getSelector();
3720 comp = intent.getComponent();
3724 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
3725 final ProviderInfo pi = getProviderInfo(comp, flags, userId);
3727 final ResolveInfo ri = new ResolveInfo();
3728 ri.providerInfo = pi;
3735 synchronized (mPackages) {
3736 String pkgName = intent.getPackage();
3737 if (pkgName == null) {
3738 return mProviders.queryIntent(intent, resolvedType, flags, userId);
3740 final PackageParser.Package pkg = mPackages.get(pkgName);
3742 return mProviders.queryIntentForPackage(
3743 intent, resolvedType, flags, pkg.providers, userId);
3750 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
3751 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
3753 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages");
3756 synchronized (mPackages) {
3757 ArrayList<PackageInfo> list;
3758 if (listUninstalled) {
3759 list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
3760 for (PackageSetting ps : mSettings.mPackages.values()) {
3762 if (ps.pkg != null) {
3763 pi = generatePackageInfo(ps.pkg, flags, userId);
3765 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
3772 list = new ArrayList<PackageInfo>(mPackages.size());
3773 for (PackageParser.Package p : mPackages.values()) {
3774 PackageInfo pi = generatePackageInfo(p, flags, userId);
3781 return new ParceledListSlice<PackageInfo>(list);
3785 private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
3786 String[] permissions, boolean[] tmp, int flags, int userId) {
3788 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3789 for (int i=0; i<permissions.length; i++) {
3790 if (gp.grantedPermissions.contains(permissions[i])) {
3797 if (numMatch == 0) {
3801 if (ps.pkg != null) {
3802 pi = generatePackageInfo(ps.pkg, flags, userId);
3804 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
3806 // The above might return null in cases of uninstalled apps or install-state
3807 // skew across users/profiles.
3809 if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
3810 if (numMatch == permissions.length) {
3811 pi.requestedPermissions = permissions;
3813 pi.requestedPermissions = new String[numMatch];
3815 for (int i=0; i<permissions.length; i++) {
3817 pi.requestedPermissions[numMatch] = permissions[i];
3828 public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
3829 String[] permissions, int flags, int userId) {
3830 if (!sUserManager.exists(userId)) return null;
3831 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
3834 synchronized (mPackages) {
3835 ArrayList<PackageInfo> list = new ArrayList<PackageInfo>();
3836 boolean[] tmpBools = new boolean[permissions.length];
3837 if (listUninstalled) {
3838 for (PackageSetting ps : mSettings.mPackages.values()) {
3839 addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId);
3842 for (PackageParser.Package pkg : mPackages.values()) {
3843 PackageSetting ps = (PackageSetting)pkg.mExtras;
3845 addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
3851 return new ParceledListSlice<PackageInfo>(list);
3856 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
3857 if (!sUserManager.exists(userId)) return null;
3858 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
3861 synchronized (mPackages) {
3862 ArrayList<ApplicationInfo> list;
3863 if (listUninstalled) {
3864 list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
3865 for (PackageSetting ps : mSettings.mPackages.values()) {
3867 if (ps.pkg != null) {
3868 ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
3869 ps.readUserState(userId), userId);
3871 ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
3878 list = new ArrayList<ApplicationInfo>(mPackages.size());
3879 for (PackageParser.Package p : mPackages.values()) {
3880 if (p.mExtras != null) {
3881 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
3882 ((PackageSetting)p.mExtras).readUserState(userId), userId);
3890 return new ParceledListSlice<ApplicationInfo>(list);
3894 public List<ApplicationInfo> getPersistentApplications(int flags) {
3895 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
3898 synchronized (mPackages) {
3899 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
3900 final int userId = UserHandle.getCallingUserId();
3901 while (i.hasNext()) {
3902 final PackageParser.Package p = i.next();
3903 if (p.applicationInfo != null
3904 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
3905 && (!mSafeMode || isSystemApp(p))) {
3906 PackageSetting ps = mSettings.mPackages.get(p.packageName);
3908 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
3909 ps.readUserState(userId), userId);
3922 public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
3923 if (!sUserManager.exists(userId)) return null;
3925 synchronized (mPackages) {
3926 final PackageParser.Provider provider = mProvidersByAuthority.get(name);
3927 PackageSetting ps = provider != null
3928 ? mSettings.mPackages.get(provider.owner.packageName)
3931 && mSettings.isEnabledLPr(provider.info, flags, userId)
3932 && (!mSafeMode || (provider.info.applicationInfo.flags
3933 &ApplicationInfo.FLAG_SYSTEM) != 0)
3934 ? PackageParser.generateProviderInfo(provider, flags,
3935 ps.readUserState(userId), userId)
3944 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
3946 synchronized (mPackages) {
3947 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority
3948 .entrySet().iterator();
3949 final int userId = UserHandle.getCallingUserId();
3950 while (i.hasNext()) {
3951 Map.Entry<String, PackageParser.Provider> entry = i.next();
3952 PackageParser.Provider p = entry.getValue();
3953 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
3955 if (ps != null && p.syncable
3956 && (!mSafeMode || (p.info.applicationInfo.flags
3957 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
3958 ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
3959 ps.readUserState(userId), userId);
3961 outNames.add(entry.getKey());
3970 public List<ProviderInfo> queryContentProviders(String processName,
3971 int uid, int flags) {
3972 ArrayList<ProviderInfo> finalList = null;
3974 synchronized (mPackages) {
3975 final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
3976 final int userId = processName != null ?
3977 UserHandle.getUserId(uid) : UserHandle.getCallingUserId();
3978 while (i.hasNext()) {
3979 final PackageParser.Provider p = i.next();
3980 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
3981 if (ps != null && p.info.authority != null
3982 && (processName == null
3983 || (p.info.processName.equals(processName)
3984 && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
3985 && mSettings.isEnabledLPr(p.info, flags, userId)
3987 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
3988 if (finalList == null) {
3989 finalList = new ArrayList<ProviderInfo>(3);
3991 ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
3992 ps.readUserState(userId), userId);
3994 finalList.add(info);
4000 if (finalList != null) {
4001 Collections.sort(finalList, mProviderInitOrderSorter);
4008 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
4011 synchronized (mPackages) {
4012 final PackageParser.Instrumentation i = mInstrumentation.get(name);
4013 return PackageParser.generateInstrumentationInfo(i, flags);
4018 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
4020 ArrayList<InstrumentationInfo> finalList =
4021 new ArrayList<InstrumentationInfo>();
4024 synchronized (mPackages) {
4025 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
4026 while (i.hasNext()) {
4027 final PackageParser.Instrumentation p = i.next();
4028 if (targetPackage == null
4029 || targetPackage.equals(p.info.targetPackage)) {
4030 InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p,
4042 private void createIdmapsForPackageLI(PackageParser.Package pkg) {
4043 ArrayMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName);
4044 if (overlays == null) {
4045 Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages");
4048 for (PackageParser.Package opkg : overlays.values()) {
4049 // Not much to do if idmap fails: we already logged the error
4050 // and we certainly don't want to abort installation of pkg simply
4051 // because an overlay didn't fit properly. For these reasons,
4052 // ignore the return value of createIdmapForPackagePairLI.
4053 createIdmapForPackagePairLI(pkg, opkg);
4057 private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
4058 PackageParser.Package opkg) {
4059 if (!opkg.mTrustedOverlay) {
4060 Slog.w(TAG, "Skipping target and overlay pair " + pkg.baseCodePath + " and " +
4061 opkg.baseCodePath + ": overlay not trusted");
4064 ArrayMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
4065 if (overlaySet == null) {
4066 Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " +
4067 opkg.baseCodePath + " but target package has no known overlays");
4070 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
4071 // TODO: generate idmap for split APKs
4072 if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid) != 0) {
4073 Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
4074 + opkg.baseCodePath);
4077 PackageParser.Package[] overlayArray =
4078 overlaySet.values().toArray(new PackageParser.Package[0]);
4079 Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
4080 public int compare(PackageParser.Package p1, PackageParser.Package p2) {
4081 return p1.mOverlayPriority - p2.mOverlayPriority;
4084 Arrays.sort(overlayArray, cmp);
4086 pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
4088 for (PackageParser.Package p : overlayArray) {
4089 pkg.applicationInfo.resourceDirs[i++] = p.baseCodePath;
4094 private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
4095 final File[] files = dir.listFiles();
4096 if (ArrayUtils.isEmpty(files)) {
4097 Log.d(TAG, "No files in app dir " + dir);
4101 if (DEBUG_PACKAGE_SCANNING) {
4102 Log.d(TAG, "Scanning app dir " + dir + " scanFlags=" + scanFlags
4103 + " flags=0x" + Integer.toHexString(parseFlags));
4106 for (File file : files) {
4107 final boolean isPackage = (isApkFile(file) || file.isDirectory())
4108 && !PackageInstallerService.isStageName(file.getName());
4110 // Ignore entries which are not packages
4114 scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
4115 scanFlags, currentTime, null);
4116 } catch (PackageManagerException e) {
4117 Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
4119 // Delete invalid userdata apps
4120 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
4121 e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
4122 logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
4123 if (file.isDirectory()) {
4124 FileUtils.deleteContents(file);
4132 private static File getSettingsProblemFile() {
4133 File dataDir = Environment.getDataDirectory();
4134 File systemDir = new File(dataDir, "system");
4135 File fname = new File(systemDir, "uiderrors.txt");
4139 static void reportSettingsProblem(int priority, String msg) {
4140 logCriticalInfo(priority, msg);
4143 static void logCriticalInfo(int priority, String msg) {
4144 Slog.println(priority, TAG, msg);
4145 EventLogTags.writePmCriticalInfo(msg);
4147 File fname = getSettingsProblemFile();
4148 FileOutputStream out = new FileOutputStream(fname, true);
4149 PrintWriter pw = new FastPrintWriter(out);
4150 SimpleDateFormat formatter = new SimpleDateFormat();
4151 String dateString = formatter.format(new Date(System.currentTimeMillis()));
4152 pw.println(dateString + ": " + msg);
4154 FileUtils.setPermissions(
4156 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
4158 } catch (java.io.IOException e) {
4162 private void collectCertificatesLI(PackageParser pp, PackageSetting ps,
4163 PackageParser.Package pkg, File srcFile, int parseFlags)
4164 throws PackageManagerException {
4166 && ps.codePath.equals(srcFile)
4167 && ps.timeStamp == srcFile.lastModified()
4168 && !isCompatSignatureUpdateNeeded(pkg)) {
4169 long mSigningKeySetId = ps.keySetData.getProperSigningKeySet();
4170 if (ps.signatures.mSignatures != null
4171 && ps.signatures.mSignatures.length != 0
4172 && mSigningKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) {
4173 // Optimization: reuse the existing cached certificates
4174 // if the package appears to be unchanged.
4175 pkg.mSignatures = ps.signatures.mSignatures;
4176 KeySetManagerService ksms = mSettings.mKeySetManagerService;
4177 synchronized (mPackages) {
4178 pkg.mSigningKeys = ksms.getPublicKeysFromKeySetLPr(mSigningKeySetId);
4183 Slog.w(TAG, "PackageSetting for " + ps.name
4184 + " is missing signatures. Collecting certs again to recover them.");
4186 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
4190 pp.collectCertificates(pkg, parseFlags);
4191 pp.collectManifestDigest(pkg);
4192 } catch (PackageParserException e) {
4193 throw PackageManagerException.from(e);
4198 * Scan a package and return the newly parsed package.
4199 * Returns null in case of errors and the error code is stored in mLastScanError
4201 private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
4202 long currentTime, UserHandle user) throws PackageManagerException {
4203 if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
4204 parseFlags |= mDefParseFlags;
4205 PackageParser pp = new PackageParser();
4206 pp.setSeparateProcesses(mSeparateProcesses);
4207 pp.setOnlyCoreApps(mOnlyCore);
4208 pp.setDisplayMetrics(mMetrics);
4210 if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
4211 parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
4214 final PackageParser.Package pkg;
4216 pkg = pp.parsePackage(scanFile, parseFlags);
4217 } catch (PackageParserException e) {
4218 throw PackageManagerException.from(e);
4221 PackageSetting ps = null;
4222 PackageSetting updatedPkg;
4224 synchronized (mPackages) {
4225 // Look to see if we already know about this package.
4226 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
4227 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
4228 // This package has been renamed to its original name. Let's
4230 ps = mSettings.peekPackageLPr(oldName);
4232 // If there was no original package, see one for the real package name.
4234 ps = mSettings.peekPackageLPr(pkg.packageName);
4236 // Check to see if this package could be hiding/updating a system
4237 // package. Must look for it either under the original or real
4238 // package name depending on our state.
4239 updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
4240 if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
4242 boolean updatedPkgBetter = false;
4243 // First check if this is a system package that may involve an update
4244 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
4245 if (ps != null && !ps.codePath.equals(scanFile)) {
4246 // The path has changed from what was last scanned... check the
4247 // version of the new path against what we have stored to determine
4249 if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
4250 if (pkg.mVersionCode < ps.versionCode) {
4251 // The system package has been updated and the code path does not match
4252 // Ignore entry. Skip it.
4253 logCriticalInfo(Log.INFO, "Package " + ps.name + " at " + scanFile
4254 + " ignored: updated version " + ps.versionCode
4255 + " better than this " + pkg.mVersionCode);
4256 if (!updatedPkg.codePath.equals(scanFile)) {
4257 Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
4258 + ps.name + " changing from " + updatedPkg.codePathString
4259 + " to " + scanFile);
4260 updatedPkg.codePath = scanFile;
4261 updatedPkg.codePathString = scanFile.toString();
4262 // This is the point at which we know that the system-disk APK
4263 // for this package has moved during a reboot (e.g. due to an OTA),
4264 // so we need to reevaluate it for privilege policy.
4265 if (locationIsPrivileged(scanFile)) {
4266 updatedPkg.pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
4269 updatedPkg.pkg = pkg;
4270 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, null);
4272 // The current app on the system partition is better than
4273 // what we have updated to on the data partition; switch
4274 // back to the system partition version.
4275 // At this point, its safely assumed that package installation for
4276 // apps in system partition will go through. If not there won't be a working
4277 // version of the app
4279 synchronized (mPackages) {
4280 // Just remove the loaded entries from package lists.
4281 mPackages.remove(ps.name);
4284 logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
4285 + " reverting from " + ps.codePathString
4286 + ": new version " + pkg.mVersionCode
4287 + " better than installed " + ps.versionCode);
4289 InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
4290 ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
4291 getAppDexInstructionSets(ps));
4292 synchronized (mInstallLock) {
4293 args.cleanUpResourcesLI();
4295 synchronized (mPackages) {
4296 mSettings.enableSystemPackageLPw(ps.name);
4298 updatedPkgBetter = true;
4303 if (updatedPkg != null) {
4304 // An updated system app will not have the PARSE_IS_SYSTEM flag set
4306 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
4308 // An updated privileged app will not have the PARSE_IS_PRIVILEGED
4309 // flag set initially
4310 if ((updatedPkg.pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
4311 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
4315 // Verify certificates against what was last scanned
4316 collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);
4319 * A new system app appeared, but we already had a non-system one of the
4320 * same name installed earlier.
4322 boolean shouldHideSystemApp = false;
4323 if (updatedPkg == null && ps != null
4324 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
4326 * Check to make sure the signatures match first. If they don't,
4327 * wipe the installed application and its data.
4329 if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
4330 != PackageManager.SIGNATURE_MATCH) {
4331 logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
4332 + " signatures don't match existing userdata copy; removing");
4333 deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
4337 * If the newly-added system app is an older version than the
4338 * already installed version, hide it. It will be scanned later
4339 * and re-added like an update.
4341 if (pkg.mVersionCode < ps.versionCode) {
4342 shouldHideSystemApp = true;
4343 logCriticalInfo(Log.INFO, "Package " + ps.name + " appeared at " + scanFile
4344 + " but new version " + pkg.mVersionCode + " better than installed "
4345 + ps.versionCode + "; hiding system");
4348 * The newly found system app is a newer version that the
4349 * one previously installed. Simply remove the
4350 * already-installed application and replace it with our own
4351 * while keeping the application data.
4353 logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
4354 + " reverting from " + ps.codePathString + ": new version "
4355 + pkg.mVersionCode + " better than installed " + ps.versionCode);
4356 InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
4357 ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
4358 getAppDexInstructionSets(ps));
4359 synchronized (mInstallLock) {
4360 args.cleanUpResourcesLI();
4366 // The apk is forward locked (not public) if its code and resources
4367 // are kept in different files. (except for app in either system or
4369 // TODO grab this value from PackageSettings
4370 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
4371 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
4372 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
4376 // TODO: extend to support forward-locked splits
4377 String resourcePath = null;
4378 String baseResourcePath = null;
4379 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
4380 if (ps != null && ps.resourcePathString != null) {
4381 resourcePath = ps.resourcePathString;
4382 baseResourcePath = ps.resourcePathString;
4384 // Should not happen at all. Just log an error.
4385 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
4388 resourcePath = pkg.codePath;
4389 baseResourcePath = pkg.baseCodePath;
4392 // Set application objects path explicitly.
4393 pkg.applicationInfo.setCodePath(pkg.codePath);
4394 pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
4395 pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
4396 pkg.applicationInfo.setResourcePath(resourcePath);
4397 pkg.applicationInfo.setBaseResourcePath(baseResourcePath);
4398 pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
4400 // Note that we invoke the following method only if we are about to unpack an application
4401 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
4402 | SCAN_UPDATE_SIGNATURE, currentTime, user);
4405 * If the system app should be overridden by a previously installed
4406 * data, hide the system app now and let the /data/app scan pick it up
4409 if (shouldHideSystemApp) {
4410 synchronized (mPackages) {
4412 * We have to grant systems permissions before we hide, because
4413 * grantPermissions will assume the package update is trying to
4414 * expand its permissions.
4416 grantPermissionsLPw(pkg, true, pkg.packageName);
4417 mSettings.disableSystemPackageLPw(pkg.packageName);
4424 private static String fixProcessName(String defProcessName,
4425 String processName, int uid) {
4426 if (processName == null) {
4427 return defProcessName;
4432 private void verifySignaturesLP(PackageSetting pkgSetting, PackageParser.Package pkg)
4433 throws PackageManagerException {
4434 if (pkgSetting.signatures.mSignatures != null) {
4435 // Already existing package. Make sure signatures match
4436 boolean match = compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures)
4437 == PackageManager.SIGNATURE_MATCH;
4439 match = compareSignaturesCompat(pkgSetting.signatures, pkg)
4440 == PackageManager.SIGNATURE_MATCH;
4443 throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
4444 + pkg.packageName + " signatures do not match the "
4445 + "previously installed version; ignoring!");
4449 // Check for shared user signatures
4450 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
4451 // Already existing package. Make sure signatures match
4452 boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
4453 pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
4455 match = compareSignaturesCompat(pkgSetting.sharedUser.signatures, pkg)
4456 == PackageManager.SIGNATURE_MATCH;
4459 throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
4460 "Package " + pkg.packageName
4461 + " has no signatures that match those in shared user "
4462 + pkgSetting.sharedUser.name + "; ignoring!");
4468 * Enforces that only the system UID or root's UID can call a method exposed
4471 * @param message used as message if SecurityException is thrown
4472 * @throws SecurityException if the caller is not system or root
4474 private static final void enforceSystemOrRoot(String message) {
4475 final int uid = Binder.getCallingUid();
4476 if (uid != Process.SYSTEM_UID && uid != 0) {
4477 throw new SecurityException(message);
4482 public void performBootDexOpt() {
4483 enforceSystemOrRoot("Only the system can request dexopt be performed");
4485 final ArraySet<PackageParser.Package> pkgs;
4486 synchronized (mPackages) {
4487 pkgs = mDeferredDexOpt;
4488 mDeferredDexOpt = null;
4492 // Sort apps by importance for dexopt ordering. Important apps are given more priority
4493 // in case the device runs out of space.
4494 ArrayList<PackageParser.Package> sortedPkgs = new ArrayList<PackageParser.Package>();
4495 // Give priority to core apps.
4496 for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
4497 PackageParser.Package pkg = it.next();
4500 Log.i(TAG, "Adding core app " + sortedPkgs.size() + ": " + pkg.packageName);
4502 sortedPkgs.add(pkg);
4506 // Give priority to system apps that listen for pre boot complete.
4507 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
4508 ArraySet<String> pkgNames = getPackageNamesForIntent(intent);
4509 for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
4510 PackageParser.Package pkg = it.next();
4511 if (pkgNames.contains(pkg.packageName)) {
4513 Log.i(TAG, "Adding pre boot system app " + sortedPkgs.size() + ": " + pkg.packageName);
4515 sortedPkgs.add(pkg);
4519 // Give priority to system apps.
4520 for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
4521 PackageParser.Package pkg = it.next();
4522 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
4524 Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName);
4526 sortedPkgs.add(pkg);
4530 // Give priority to updated system apps.
4531 for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
4532 PackageParser.Package pkg = it.next();
4533 if (isUpdatedSystemApp(pkg)) {
4535 Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName);
4537 sortedPkgs.add(pkg);
4541 // Give priority to apps that listen for boot complete.
4542 intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
4543 pkgNames = getPackageNamesForIntent(intent);
4544 for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
4545 PackageParser.Package pkg = it.next();
4546 if (pkgNames.contains(pkg.packageName)) {
4548 Log.i(TAG, "Adding boot app " + sortedPkgs.size() + ": " + pkg.packageName);
4550 sortedPkgs.add(pkg);
4554 // Filter out packages that aren't recently used.
4555 filterRecentlyUsedApps(pkgs);
4556 // Add all remaining apps.
4557 for (PackageParser.Package pkg : pkgs) {
4559 Log.i(TAG, "Adding app " + sortedPkgs.size() + ": " + pkg.packageName);
4561 sortedPkgs.add(pkg);
4564 // If we want to be lazy, filter everything that wasn't recently used.
4566 filterRecentlyUsedApps(sortedPkgs);
4570 int total = sortedPkgs.size();
4571 File dataDir = Environment.getDataDirectory();
4572 long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
4573 if (lowThreshold == 0) {
4574 throw new IllegalStateException("Invalid low memory threshold");
4576 for (PackageParser.Package pkg : sortedPkgs) {
4577 long usableSpace = dataDir.getUsableSpace();
4578 if (usableSpace < lowThreshold) {
4579 Log.w(TAG, "Not running dexopt on remaining apps due to low memory: " + usableSpace);
4582 performBootDexOpt(pkg, ++i, total);
4587 private void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs) {
4588 // Filter out packages that aren't recently used.
4590 // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
4591 // should do a full dexopt.
4592 if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
4593 int total = pkgs.size();
4595 long now = System.currentTimeMillis();
4596 for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
4597 PackageParser.Package pkg = i.next();
4598 long then = pkg.mLastPackageUsageTimeInMills;
4599 if (then + mDexOptLRUThresholdInMills < now) {
4601 Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
4602 ((then == 0) ? "never" : new Date(then)));
4609 Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
4614 private ArraySet<String> getPackageNamesForIntent(Intent intent) {
4615 List<ResolveInfo> ris = null;
4617 ris = AppGlobals.getPackageManager().queryIntentReceivers(
4618 intent, null, 0, UserHandle.USER_OWNER);
4619 } catch (RemoteException e) {
4621 ArraySet<String> pkgNames = new ArraySet<String>();
4623 for (ResolveInfo ri : ris) {
4624 pkgNames.add(ri.activityInfo.packageName);
4630 private void performBootDexOpt(PackageParser.Package pkg, int curr, int total) {
4632 Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName);
4634 if (!isFirstBoot()) {
4636 ActivityManagerNative.getDefault().showBootMessage(
4637 mContext.getResources().getString(R.string.android_upgrading_apk,
4638 curr, total), true);
4639 } catch (RemoteException e) {
4642 PackageParser.Package p = pkg;
4643 synchronized (mInstallLock) {
4644 performDexOptLI(p, null /* instruction sets */, false /* force dex */,
4645 false /* defer */, true /* include dependencies */);
4650 public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
4651 return performDexOpt(packageName, instructionSet, false);
4654 private static String getPrimaryInstructionSet(ApplicationInfo info) {
4655 if (info.primaryCpuAbi == null) {
4656 return getPreferredInstructionSet();
4659 return VMRuntime.getInstructionSet(info.primaryCpuAbi);
4662 public boolean performDexOpt(String packageName, String instructionSet, boolean backgroundDexopt) {
4663 boolean dexopt = mLazyDexOpt || backgroundDexopt;
4664 boolean updateUsage = !backgroundDexopt; // Don't update usage if this is just a backgroundDexopt
4665 if (!dexopt && !updateUsage) {
4666 // We aren't going to dexopt or update usage, so bail early.
4669 PackageParser.Package p;
4670 final String targetInstructionSet;
4671 synchronized (mPackages) {
4672 p = mPackages.get(packageName);
4677 p.mLastPackageUsageTimeInMills = System.currentTimeMillis();
4679 mPackageUsage.write(false);
4681 // We aren't going to dexopt, so bail early.
4685 targetInstructionSet = instructionSet != null ? instructionSet :
4686 getPrimaryInstructionSet(p.applicationInfo);
4687 if (p.mDexOptPerformed.contains(targetInstructionSet)) {
4692 synchronized (mInstallLock) {
4693 final String[] instructionSets = new String[] { targetInstructionSet };
4694 return performDexOptLI(p, instructionSets, false /* force dex */, false /* defer */,
4695 true /* include dependencies */) == DEX_OPT_PERFORMED;
4699 public ArraySet<String> getPackagesThatNeedDexOpt() {
4700 ArraySet<String> pkgs = null;
4701 synchronized (mPackages) {
4702 for (PackageParser.Package p : mPackages.values()) {
4704 Log.i(TAG, p.packageName + " mDexOptPerformed=" + p.mDexOptPerformed.toArray());
4706 if (!p.mDexOptPerformed.isEmpty()) {
4710 pkgs = new ArraySet<String>();
4712 pkgs.add(p.packageName);
4718 public void shutdown() {
4719 mPackageUsage.write(true);
4722 private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets,
4723 boolean forceDex, boolean defer, ArraySet<String> done) {
4724 for (int i=0; i<libs.size(); i++) {
4725 PackageParser.Package libPkg;
4727 synchronized (mPackages) {
4728 libName = libs.get(i);
4729 SharedLibraryEntry lib = mSharedLibraries.get(libName);
4730 if (lib != null && lib.apk != null) {
4731 libPkg = mPackages.get(lib.apk);
4736 if (libPkg != null && !done.contains(libName)) {
4737 performDexOptLI(libPkg, instructionSets, forceDex, defer, done);
4742 static final int DEX_OPT_SKIPPED = 0;
4743 static final int DEX_OPT_PERFORMED = 1;
4744 static final int DEX_OPT_DEFERRED = 2;
4745 static final int DEX_OPT_FAILED = -1;
4747 private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
4748 boolean forceDex, boolean defer, ArraySet<String> done) {
4749 final String[] instructionSets = targetInstructionSets != null ?
4750 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
4753 done.add(pkg.packageName);
4754 if (pkg.usesLibraries != null) {
4755 performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer, done);
4757 if (pkg.usesOptionalLibraries != null) {
4758 performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, forceDex, defer, done);
4762 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) {
4763 return DEX_OPT_SKIPPED;
4766 final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
4768 final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
4769 boolean performedDexOpt = false;
4770 // There are three basic cases here:
4771 // 1.) we need to dexopt, either because we are forced or it is needed
4772 // 2.) we are defering a needed dexopt
4773 // 3.) we are skipping an unneeded dexopt
4774 final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
4775 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
4776 if (!forceDex && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) {
4780 for (String path : paths) {
4782 // This will return DEXOPT_NEEDED if we either cannot find any odex file for this
4783 // patckage or the one we find does not match the image checksum (i.e. it was
4784 // compiled against an old image). It will return PATCHOAT_NEEDED if we can find a
4785 // odex file and it matches the checksum of the image but not its base address,
4786 // meaning we need to move it.
4787 final byte isDexOptNeeded = DexFile.isDexOptNeededInternal(path,
4788 pkg.packageName, dexCodeInstructionSet, defer);
4789 if (forceDex || (!defer && isDexOptNeeded == DexFile.DEXOPT_NEEDED)) {
4790 Log.i(TAG, "Running dexopt on: " + path + " pkg="
4791 + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
4792 + " vmSafeMode=" + vmSafeMode);
4793 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
4794 final int ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
4795 pkg.packageName, dexCodeInstructionSet, vmSafeMode);
4798 // Don't bother running dexopt again if we failed, it will probably
4799 // just result in an error again. Also, don't bother dexopting for other
4801 return DEX_OPT_FAILED;
4804 performedDexOpt = true;
4805 } else if (!defer && isDexOptNeeded == DexFile.PATCHOAT_NEEDED) {
4806 Log.i(TAG, "Running patchoat on: " + pkg.applicationInfo.packageName);
4807 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
4808 final int ret = mInstaller.patchoat(path, sharedGid, !isForwardLocked(pkg),
4809 pkg.packageName, dexCodeInstructionSet);
4812 // Don't bother running patchoat again if we failed, it will probably
4813 // just result in an error again. Also, don't bother dexopting for other
4815 return DEX_OPT_FAILED;
4818 performedDexOpt = true;
4821 // We're deciding to defer a needed dexopt. Don't bother dexopting for other
4822 // paths and instruction sets. We'll deal with them all together when we process
4823 // our list of deferred dexopts.
4824 if (defer && isDexOptNeeded != DexFile.UP_TO_DATE) {
4825 if (mDeferredDexOpt == null) {
4826 mDeferredDexOpt = new ArraySet<PackageParser.Package>();
4828 mDeferredDexOpt.add(pkg);
4829 return DEX_OPT_DEFERRED;
4831 } catch (FileNotFoundException e) {
4832 Slog.w(TAG, "Apk not found for dexopt: " + path);
4833 return DEX_OPT_FAILED;
4834 } catch (IOException e) {
4835 Slog.w(TAG, "IOException reading apk: " + path, e);
4836 return DEX_OPT_FAILED;
4837 } catch (StaleDexCacheError e) {
4838 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
4839 return DEX_OPT_FAILED;
4840 } catch (Exception e) {
4841 Slog.w(TAG, "Exception when doing dexopt : ", e);
4842 return DEX_OPT_FAILED;
4846 // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
4847 // either have either succeeded dexopt, or have had isDexOptNeededInternal tell us
4848 // it isn't required. We therefore mark that this package doesn't need dexopt unless
4849 // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
4851 pkg.mDexOptPerformed.add(dexCodeInstructionSet);
4854 // If we've gotten here, we're sure that no error occurred and that we haven't
4855 // deferred dex-opt. We've either dex-opted one more paths or instruction sets or
4856 // we've skipped all of them because they are up to date. In both cases this
4857 // package doesn't need dexopt any longer.
4858 return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
4861 private static String[] getAppDexInstructionSets(ApplicationInfo info) {
4862 if (info.primaryCpuAbi != null) {
4863 if (info.secondaryCpuAbi != null) {
4864 return new String[] {
4865 VMRuntime.getInstructionSet(info.primaryCpuAbi),
4866 VMRuntime.getInstructionSet(info.secondaryCpuAbi) };
4868 return new String[] {
4869 VMRuntime.getInstructionSet(info.primaryCpuAbi) };
4873 return new String[] { getPreferredInstructionSet() };
4876 private static String[] getAppDexInstructionSets(PackageSetting ps) {
4877 if (ps.primaryCpuAbiString != null) {
4878 if (ps.secondaryCpuAbiString != null) {
4879 return new String[] {
4880 VMRuntime.getInstructionSet(ps.primaryCpuAbiString),
4881 VMRuntime.getInstructionSet(ps.secondaryCpuAbiString) };
4883 return new String[] {
4884 VMRuntime.getInstructionSet(ps.primaryCpuAbiString) };
4888 return new String[] { getPreferredInstructionSet() };
4891 private static String getPreferredInstructionSet() {
4892 if (sPreferredInstructionSet == null) {
4893 sPreferredInstructionSet = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
4896 return sPreferredInstructionSet;
4899 private static List<String> getAllInstructionSets() {
4900 final String[] allAbis = Build.SUPPORTED_ABIS;
4901 final List<String> allInstructionSets = new ArrayList<String>(allAbis.length);
4903 for (String abi : allAbis) {
4904 final String instructionSet = VMRuntime.getInstructionSet(abi);
4905 if (!allInstructionSets.contains(instructionSet)) {
4906 allInstructionSets.add(instructionSet);
4910 return allInstructionSets;
4914 * Returns the instruction set that should be used to compile dex code. In the presence of
4915 * a native bridge this might be different than the one shared libraries use.
4917 private static String getDexCodeInstructionSet(String sharedLibraryIsa) {
4918 String dexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + sharedLibraryIsa);
4919 return (dexCodeIsa.isEmpty() ? sharedLibraryIsa : dexCodeIsa);
4922 private static String[] getDexCodeInstructionSets(String[] instructionSets) {
4923 ArraySet<String> dexCodeInstructionSets = new ArraySet<String>(instructionSets.length);
4924 for (String instructionSet : instructionSets) {
4925 dexCodeInstructionSets.add(getDexCodeInstructionSet(instructionSet));
4927 return dexCodeInstructionSets.toArray(new String[dexCodeInstructionSets.size()]);
4931 * Returns deduplicated list of supported instructions for dex code.
4933 public static String[] getAllDexCodeInstructionSets() {
4934 String[] supportedInstructionSets = new String[Build.SUPPORTED_ABIS.length];
4935 for (int i = 0; i < supportedInstructionSets.length; i++) {
4936 String abi = Build.SUPPORTED_ABIS[i];
4937 supportedInstructionSets[i] = VMRuntime.getInstructionSet(abi);
4939 return getDexCodeInstructionSets(supportedInstructionSets);
4943 public void forceDexOpt(String packageName) {
4944 enforceSystemOrRoot("forceDexOpt");
4946 PackageParser.Package pkg;
4947 synchronized (mPackages) {
4948 pkg = mPackages.get(packageName);
4950 throw new IllegalArgumentException("Missing package: " + packageName);
4954 synchronized (mInstallLock) {
4955 final String[] instructionSets = new String[] {
4956 getPrimaryInstructionSet(pkg.applicationInfo) };
4957 final int res = performDexOptLI(pkg, instructionSets, true, false, true);
4958 if (res != DEX_OPT_PERFORMED) {
4959 throw new IllegalStateException("Failed to dexopt: " + res);
4964 private int performDexOptLI(PackageParser.Package pkg, String[] instructionSets,
4965 boolean forceDex, boolean defer, boolean inclDependencies) {
4966 ArraySet<String> done;
4967 if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
4968 done = new ArraySet<String>();
4969 done.add(pkg.packageName);
4973 return performDexOptLI(pkg, instructionSets, forceDex, defer, done);
4976 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
4977 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
4978 Slog.w(TAG, "Unable to update from " + oldPkg.name
4979 + " to " + newPkg.packageName
4980 + ": old package not in system partition");
4982 } else if (mPackages.get(oldPkg.name) != null) {
4983 Slog.w(TAG, "Unable to update from " + oldPkg.name
4984 + " to " + newPkg.packageName
4985 + ": old package still exists");
4991 File getDataPathForUser(int userId) {
4992 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
4995 private File getDataPathForPackage(String packageName, int userId) {
4997 * Until we fully support multiple users, return the directory we
4998 * previously would have. The PackageManagerTests will need to be
4999 * revised when this is changed back..
5002 return new File(mAppDataDir, packageName);
5004 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
5005 + File.separator + packageName);
5009 private int createDataDirsLI(String packageName, int uid, String seinfo) {
5010 int[] users = sUserManager.getUserIds();
5011 int res = mInstaller.install(packageName, uid, uid, seinfo);
5015 for (int user : users) {
5017 res = mInstaller.createUserData(packageName,
5018 UserHandle.getUid(user, uid), user, seinfo);
5027 private int removeDataDirsLI(String packageName) {
5028 int[] users = sUserManager.getUserIds();
5030 for (int user : users) {
5031 int resInner = mInstaller.remove(packageName, user);
5040 private int deleteCodeCacheDirsLI(String packageName) {
5041 int[] users = sUserManager.getUserIds();
5043 for (int user : users) {
5044 int resInner = mInstaller.deleteCodeCacheFiles(packageName, user);
5052 private void addSharedLibraryLPw(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
5053 PackageParser.Package changingLib) {
5054 if (file.path != null) {
5055 usesLibraryFiles.add(file.path);
5058 PackageParser.Package p = mPackages.get(file.apk);
5059 if (changingLib != null && changingLib.packageName.equals(file.apk)) {
5060 // If we are doing this while in the middle of updating a library apk,
5061 // then we need to make sure to use that new apk for determining the
5062 // dependencies here. (We haven't yet finished committing the new apk
5063 // to the package manager state.)
5064 if (p == null || p.packageName.equals(changingLib.packageName)) {
5069 usesLibraryFiles.addAll(p.getAllCodePaths());
5073 private void updateSharedLibrariesLPw(PackageParser.Package pkg,
5074 PackageParser.Package changingLib) throws PackageManagerException {
5075 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
5076 final ArraySet<String> usesLibraryFiles = new ArraySet<>();
5077 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
5078 for (int i=0; i<N; i++) {
5079 final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesLibraries.get(i));
5081 throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
5082 "Package " + pkg.packageName + " requires unavailable shared library "
5083 + pkg.usesLibraries.get(i) + "; failing!");
5085 addSharedLibraryLPw(usesLibraryFiles, file, changingLib);
5087 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
5088 for (int i=0; i<N; i++) {
5089 final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
5091 Slog.w(TAG, "Package " + pkg.packageName
5092 + " desires unavailable shared library "
5093 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
5095 addSharedLibraryLPw(usesLibraryFiles, file, changingLib);
5098 N = usesLibraryFiles.size();
5100 pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[N]);
5102 pkg.usesLibraryFiles = null;
5107 private static boolean hasString(List<String> list, List<String> which) {
5111 for (int i=list.size()-1; i>=0; i--) {
5112 for (int j=which.size()-1; j>=0; j--) {
5113 if (which.get(j).equals(list.get(i))) {
5121 private void updateAllSharedLibrariesLPw() {
5122 for (PackageParser.Package pkg : mPackages.values()) {
5124 updateSharedLibrariesLPw(pkg, null);
5125 } catch (PackageManagerException e) {
5126 Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
5131 private ArrayList<PackageParser.Package> updateAllSharedLibrariesLPw(
5132 PackageParser.Package changingPkg) {
5133 ArrayList<PackageParser.Package> res = null;
5134 for (PackageParser.Package pkg : mPackages.values()) {
5135 if (hasString(pkg.usesLibraries, changingPkg.libraryNames)
5136 || hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames)) {
5138 res = new ArrayList<PackageParser.Package>();
5142 updateSharedLibrariesLPw(pkg, changingPkg);
5143 } catch (PackageManagerException e) {
5144 Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
5152 * Derive the value of the {@code cpuAbiOverride} based on the provided
5153 * value and an optional stored value from the package settings.
5155 private static String deriveAbiOverride(String abiOverride, PackageSetting settings) {
5156 String cpuAbiOverride = null;
5158 if (NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
5159 cpuAbiOverride = null;
5160 } else if (abiOverride != null) {
5161 cpuAbiOverride = abiOverride;
5162 } else if (settings != null) {
5163 cpuAbiOverride = settings.cpuAbiOverrideString;
5166 return cpuAbiOverride;
5169 private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
5170 int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
5171 boolean success = false;
5173 final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
5178 if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
5179 removeDataDirsLI(pkg.packageName);
5184 private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
5185 int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
5186 final File scanFile = new File(pkg.codePath);
5187 if (pkg.applicationInfo.getCodePath() == null ||
5188 pkg.applicationInfo.getResourcePath() == null) {
5189 // Bail out. The resource and code paths haven't been set.
5190 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
5191 "Code and resource paths haven't been set correctly");
5194 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
5195 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
5197 // Only allow system apps to be flagged as core apps.
5198 pkg.coreApp = false;
5201 if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
5202 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED;
5205 if (mCustomResolverComponentName != null &&
5206 mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
5207 setUpCustomResolverActivity(pkg);
5210 if (pkg.packageName.equals("android")) {
5211 synchronized (mPackages) {
5212 if (mAndroidApplication != null) {
5213 Slog.w(TAG, "*************************************************");
5214 Slog.w(TAG, "Core android package being redefined. Skipping.");
5215 Slog.w(TAG, " file=" + scanFile);
5216 Slog.w(TAG, "*************************************************");
5217 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
5218 "Core android package being redefined. Skipping.");
5221 // Set up information for our fall-back user intent resolution activity.
5222 mPlatformPackage = pkg;
5223 pkg.mVersionCode = mSdkVersion;
5224 mAndroidApplication = pkg.applicationInfo;
5226 if (!mResolverReplaced) {
5227 mResolveActivity.applicationInfo = mAndroidApplication;
5228 mResolveActivity.name = ResolverActivity.class.getName();
5229 mResolveActivity.packageName = mAndroidApplication.packageName;
5230 mResolveActivity.processName = "system:ui";
5231 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
5232 mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
5233 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
5234 mResolveActivity.theme = R.style.Theme_Holo_Dialog_Alert;
5235 mResolveActivity.exported = true;
5236 mResolveActivity.enabled = true;
5237 mResolveInfo.activityInfo = mResolveActivity;
5238 mResolveInfo.priority = 0;
5239 mResolveInfo.preferredOrder = 0;
5240 mResolveInfo.match = 0;
5241 mResolveComponentName = new ComponentName(
5242 mAndroidApplication.packageName, mResolveActivity.name);
5247 if (DEBUG_PACKAGE_SCANNING) {
5248 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
5249 Log.d(TAG, "Scanning package " + pkg.packageName);
5252 if (mPackages.containsKey(pkg.packageName)
5253 || mSharedLibraries.containsKey(pkg.packageName)) {
5254 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
5255 "Application package " + pkg.packageName
5256 + " already installed. Skipping duplicate.");
5259 // Initialize package source and resource directories
5260 File destCodeFile = new File(pkg.applicationInfo.getCodePath());
5261 File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
5263 SharedUserSetting suid = null;
5264 PackageSetting pkgSetting = null;
5266 if (!isSystemApp(pkg)) {
5267 // Only system apps can use these features.
5268 pkg.mOriginalPackages = null;
5269 pkg.mRealPackage = null;
5270 pkg.mAdoptPermissions = null;
5274 synchronized (mPackages) {
5275 if (pkg.mSharedUserId != null) {
5276 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
5278 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
5279 "Creating application package " + pkg.packageName
5280 + " for shared user failed");
5282 if (DEBUG_PACKAGE_SCANNING) {
5283 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
5284 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
5285 + "): packages=" + suid.packages);
5289 // Check if we are renaming from an original package name.
5290 PackageSetting origPackage = null;
5291 String realName = null;
5292 if (pkg.mOriginalPackages != null) {
5293 // This package may need to be renamed to a previously
5294 // installed name. Let's check on that...
5295 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
5296 if (pkg.mOriginalPackages.contains(renamed)) {
5297 // This package had originally been installed as the
5298 // original name, and we have already taken care of
5299 // transitioning to the new one. Just update the new
5300 // one to continue using the old name.
5301 realName = pkg.mRealPackage;
5302 if (!pkg.packageName.equals(renamed)) {
5303 // Callers into this function may have already taken
5304 // care of renaming the package; only do it here if
5305 // it is not already done.
5306 pkg.setPackageName(renamed);
5310 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
5311 if ((origPackage = mSettings.peekPackageLPr(
5312 pkg.mOriginalPackages.get(i))) != null) {
5313 // We do have the package already installed under its
5314 // original name... should we use it?
5315 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
5316 // New package is not compatible with original.
5319 } else if (origPackage.sharedUser != null) {
5320 // Make sure uid is compatible between packages.
5321 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
5322 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
5323 + " to " + pkg.packageName + ": old uid "
5324 + origPackage.sharedUser.name
5325 + " differs from " + pkg.mSharedUserId);
5330 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
5331 + pkg.packageName + " to old name " + origPackage.name);
5339 if (mTransferedPackages.contains(pkg.packageName)) {
5340 Slog.w(TAG, "Package " + pkg.packageName
5341 + " was transferred to another, but its .apk remains");
5344 // Just create the setting, don't add it yet. For already existing packages
5345 // the PkgSetting exists already and doesn't have to be created.
5346 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
5347 destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
5348 pkg.applicationInfo.primaryCpuAbi,
5349 pkg.applicationInfo.secondaryCpuAbi,
5350 pkg.applicationInfo.flags, user, false);
5351 if (pkgSetting == null) {
5352 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
5353 "Creating application package " + pkg.packageName + " failed");
5356 if (pkgSetting.origPackage != null) {
5357 // If we are first transitioning from an original package,
5358 // fix up the new package's name now. We need to do this after
5359 // looking up the package under its new name, so getPackageLP
5360 // can take care of fiddling things correctly.
5361 pkg.setPackageName(origPackage.name);
5363 // File a report about this.
5364 String msg = "New package " + pkgSetting.realName
5365 + " renamed to replace old package " + pkgSetting.name;
5366 reportSettingsProblem(Log.WARN, msg);
5368 // Make a note of it.
5369 mTransferedPackages.add(origPackage.name);
5371 // No longer need to retain this.
5372 pkgSetting.origPackage = null;
5375 if (realName != null) {
5376 // Make a note of it.
5377 mTransferedPackages.add(pkg.packageName);
5380 if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
5381 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
5384 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
5385 // Check all shared libraries and map to their actual file path.
5386 // We only do this here for apps not on a system dir, because those
5387 // are the only ones that can fail an install due to this. We
5388 // will take care of the system apps by updating all of their
5389 // library paths after the scan is done.
5390 updateSharedLibrariesLPw(pkg, null);
5393 if (mFoundPolicyFile) {
5394 SELinuxMMAC.assignSeinfoValue(pkg);
5397 pkg.applicationInfo.uid = pkgSetting.appId;
5398 pkg.mExtras = pkgSetting;
5399 if (!pkgSetting.keySetData.isUsingUpgradeKeySets() || pkgSetting.sharedUser != null) {
5401 verifySignaturesLP(pkgSetting, pkg);
5402 } catch (PackageManagerException e) {
5403 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
5406 // The signature has changed, but this package is in the system
5407 // image... let's recover!
5408 pkgSetting.signatures.mSignatures = pkg.mSignatures;
5409 // However... if this package is part of a shared user, but it
5410 // doesn't match the signature of the shared user, let's fail.
5411 // What this means is that you can't change the signatures
5412 // associated with an overall shared user, which doesn't seem all
5413 // that unreasonable.
5414 if (pkgSetting.sharedUser != null) {
5415 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
5416 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
5417 throw new PackageManagerException(
5418 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
5419 "Signature mismatch for shared user : "
5420 + pkgSetting.sharedUser);
5423 // File a report about this.
5424 String msg = "System package " + pkg.packageName
5425 + " signature changed; retaining data.";
5426 reportSettingsProblem(Log.WARN, msg);
5429 if (!checkUpgradeKeySetLP(pkgSetting, pkg)) {
5430 throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
5431 + pkg.packageName + " upgrade keys do not match the "
5432 + "previously installed version");
5434 // signatures may have changed as result of upgrade
5435 pkgSetting.signatures.mSignatures = pkg.mSignatures;
5438 // Verify that this new package doesn't have any content providers
5439 // that conflict with existing packages. Only do this if the
5440 // package isn't already installed, since we don't want to break
5441 // things that are installed.
5442 if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
5443 final int N = pkg.providers.size();
5445 for (i=0; i<N; i++) {
5446 PackageParser.Provider p = pkg.providers.get(i);
5447 if (p.info.authority != null) {
5448 String names[] = p.info.authority.split(";");
5449 for (int j = 0; j < names.length; j++) {
5450 if (mProvidersByAuthority.containsKey(names[j])) {
5451 PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
5452 final String otherPackageName =
5453 ((other != null && other.getComponentName() != null) ?
5454 other.getComponentName().getPackageName() : "?");
5455 throw new PackageManagerException(
5456 INSTALL_FAILED_CONFLICTING_PROVIDER,
5457 "Can't install because provider name " + names[j]
5458 + " (in package " + pkg.applicationInfo.packageName
5459 + ") is already used by " + otherPackageName);
5466 if (pkg.mAdoptPermissions != null) {
5467 // This package wants to adopt ownership of permissions from
5469 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
5470 final String origName = pkg.mAdoptPermissions.get(i);
5471 final PackageSetting orig = mSettings.peekPackageLPr(origName);
5473 if (verifyPackageUpdateLPr(orig, pkg)) {
5474 Slog.i(TAG, "Adopting permissions from " + origName + " to "
5476 mSettings.transferPermissionsLPw(origName, pkg.packageName);
5483 final String pkgName = pkg.packageName;
5485 final long scanFileTime = scanFile.lastModified();
5486 final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
5487 pkg.applicationInfo.processName = fixProcessName(
5488 pkg.applicationInfo.packageName,
5489 pkg.applicationInfo.processName,
5490 pkg.applicationInfo.uid);
5493 if (mPlatformPackage == pkg) {
5494 // The system package is special.
5495 dataPath = new File(Environment.getDataDirectory(), "system");
5497 pkg.applicationInfo.dataDir = dataPath.getPath();
5500 // This is a normal package, need to make its data directory.
5501 dataPath = getDataPathForPackage(pkg.packageName, 0);
5503 boolean uidError = false;
5504 if (dataPath.exists()) {
5507 StructStat stat = Os.stat(dataPath.getPath());
5508 currentUid = stat.st_uid;
5509 } catch (ErrnoException e) {
5510 Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
5513 // If we have mismatched owners for the data path, we have a problem.
5514 if (currentUid != pkg.applicationInfo.uid) {
5515 boolean recovered = false;
5516 if (currentUid == 0) {
5517 // The directory somehow became owned by root. Wow.
5518 // This is probably because the system was stopped while
5519 // installd was in the middle of messing with its libs
5520 // directory. Ask installd to fix that.
5521 int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
5522 pkg.applicationInfo.uid);
5525 String msg = "Package " + pkg.packageName
5526 + " unexpectedly changed to uid 0; recovered to " +
5527 + pkg.applicationInfo.uid;
5528 reportSettingsProblem(Log.WARN, msg);
5531 if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
5532 || (scanFlags&SCAN_BOOTING) != 0)) {
5533 // If this is a system app, we can at least delete its
5534 // current data so the application will still work.
5535 int ret = removeDataDirsLI(pkgName);
5537 // TODO: Kill the processes first
5539 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
5540 ? "System package " : "Third party package ";
5541 String msg = prefix + pkg.packageName
5542 + " has changed from uid: "
5543 + currentUid + " to "
5544 + pkg.applicationInfo.uid + "; old data erased";
5545 reportSettingsProblem(Log.WARN, msg);
5548 // And now re-install the app.
5549 ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
5550 pkg.applicationInfo.seinfo);
5552 // Ack should not happen!
5553 msg = prefix + pkg.packageName
5554 + " could not have data directory re-created after delete.";
5555 reportSettingsProblem(Log.WARN, msg);
5556 throw new PackageManagerException(
5557 INSTALL_FAILED_INSUFFICIENT_STORAGE, msg);
5561 mHasSystemUidErrors = true;
5563 } else if (!recovered) {
5564 // If we allow this install to proceed, we will be broken.
5566 throw new PackageManagerException(INSTALL_FAILED_UID_CHANGED,
5570 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
5571 + pkg.applicationInfo.uid + "/fs_"
5573 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
5574 pkg.applicationInfo.nativeLibraryRootDir = pkg.applicationInfo.dataDir;
5575 String msg = "Package " + pkg.packageName
5576 + " has mismatched uid: "
5577 + currentUid + " on disk, "
5578 + pkg.applicationInfo.uid + " in settings";
5580 synchronized (mPackages) {
5581 mSettings.mReadMessages.append(msg);
5582 mSettings.mReadMessages.append('\n');
5584 if (!pkgSetting.uidError) {
5585 reportSettingsProblem(Log.ERROR, msg);
5590 pkg.applicationInfo.dataDir = dataPath.getPath();
5591 if (mShouldRestoreconData) {
5592 Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
5593 mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo,
5594 pkg.applicationInfo.uid);
5597 if (DEBUG_PACKAGE_SCANNING) {
5598 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
5599 Log.v(TAG, "Want this data dir: " + dataPath);
5601 //invoke installer to do the actual installation
5602 int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
5603 pkg.applicationInfo.seinfo);
5605 // Error from installer
5606 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
5607 "Unable to create data dirs [errorCode=" + ret + "]");
5610 if (dataPath.exists()) {
5611 pkg.applicationInfo.dataDir = dataPath.getPath();
5613 Slog.w(TAG, "Unable to create data directory: " + dataPath);
5614 pkg.applicationInfo.dataDir = null;
5618 pkgSetting.uidError = uidError;
5621 final String path = scanFile.getPath();
5622 final String codePath = pkg.applicationInfo.getCodePath();
5623 final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
5624 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
5625 setBundledAppAbisAndRoots(pkg, pkgSetting);
5627 // If we haven't found any native libraries for the app, check if it has
5628 // renderscript code. We'll need to force the app to 32 bit if it has
5629 // renderscript bitcode.
5630 if (pkg.applicationInfo.primaryCpuAbi == null
5631 && pkg.applicationInfo.secondaryCpuAbi == null
5632 && Build.SUPPORTED_64_BIT_ABIS.length > 0) {
5633 NativeLibraryHelper.Handle handle = null;
5635 handle = NativeLibraryHelper.Handle.create(scanFile);
5636 if (NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
5637 pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
5639 } catch (IOException ioe) {
5640 Slog.w(TAG, "Error scanning system app : " + ioe);
5642 IoUtils.closeQuietly(handle);
5646 setNativeLibraryPaths(pkg);
5648 // TODO: We can probably be smarter about this stuff. For installed apps,
5649 // we can calculate this information at install time once and for all. For
5650 // system apps, we can probably assume that this information doesn't change
5651 // after the first boot scan. As things stand, we do lots of unnecessary work.
5653 // Give ourselves some initial paths; we'll come back for another
5654 // pass once we've determined ABI below.
5655 setNativeLibraryPaths(pkg);
5657 final boolean isAsec = isForwardLocked(pkg) || isExternal(pkg);
5658 final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
5659 final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;
5661 NativeLibraryHelper.Handle handle = null;
5663 handle = NativeLibraryHelper.Handle.create(scanFile);
5664 // TODO(multiArch): This can be null for apps that didn't go through the
5665 // usual installation process. We can calculate it again, like we
5666 // do during install time.
5668 // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
5670 final File nativeLibraryRoot = new File(nativeLibraryRootStr);
5672 // Null out the abis so that they can be recalculated.
5673 pkg.applicationInfo.primaryCpuAbi = null;
5674 pkg.applicationInfo.secondaryCpuAbi = null;
5675 if (isMultiArch(pkg.applicationInfo)) {
5676 // Warn if we've set an abiOverride for multi-lib packages..
5677 // By definition, we need to copy both 32 and 64 bit libraries for
5679 if (pkg.cpuAbiOverride != null
5680 && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
5681 Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
5684 int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
5685 int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
5686 if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
5688 abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
5690 abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
5691 nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
5692 useIsaSpecificSubdirs);
5696 maybeThrowExceptionForMultiArchCopy(
5697 "Error unpackaging 32 bit native libs for multiarch app.", abi32);
5699 if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
5701 abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
5703 abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
5704 nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
5705 useIsaSpecificSubdirs);
5709 maybeThrowExceptionForMultiArchCopy(
5710 "Error unpackaging 64 bit native libs for multiarch app.", abi64);
5713 pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
5717 final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
5719 pkg.applicationInfo.secondaryCpuAbi = abi;
5721 pkg.applicationInfo.primaryCpuAbi = abi;
5725 String[] abiList = (cpuAbiOverride != null) ?
5726 new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
5728 // Enable gross and lame hacks for apps that are built with old
5729 // SDK tools. We must scan their APKs for renderscript bitcode and
5730 // not launch them if it's present. Don't bother checking on devices
5731 // that don't have 64 bit support.
5732 boolean needsRenderScriptOverride = false;
5733 if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
5734 NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
5735 abiList = Build.SUPPORTED_32_BIT_ABIS;
5736 needsRenderScriptOverride = true;
5741 copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
5743 copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
5744 nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
5747 if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
5748 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
5749 "Error unpackaging native libs for app, errorCode=" + copyRet);
5753 pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
5754 } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
5755 pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
5756 } else if (needsRenderScriptOverride) {
5757 pkg.applicationInfo.primaryCpuAbi = abiList[0];
5760 } catch (IOException ioe) {
5761 Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
5763 IoUtils.closeQuietly(handle);
5766 // Now that we've calculated the ABIs and determined if it's an internal app,
5767 // we will go ahead and populate the nativeLibraryPath.
5768 setNativeLibraryPaths(pkg);
5770 if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
5771 final int[] userIds = sUserManager.getUserIds();
5772 synchronized (mInstallLock) {
5773 // Create a native library symlink only if we have native libraries
5774 // and if the native libraries are 32 bit libraries. We do not provide
5775 // this symlink for 64 bit libraries.
5776 if (pkg.applicationInfo.primaryCpuAbi != null &&
5777 !VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
5778 final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
5779 for (int userId : userIds) {
5780 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName, nativeLibPath, userId) < 0) {
5781 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
5782 "Failed linking native library dir (user=" + userId + ")");
5789 // This is a special case for the "system" package, where the ABI is
5790 // dictated by the zygote configuration (and init.rc). We should keep track
5791 // of this ABI so that we can deal with "normal" applications that run under
5792 // the same UID correctly.
5793 if (mPlatformPackage == pkg) {
5794 pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ?
5795 Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
5798 pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
5799 pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
5800 pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
5801 // Copy the derived override back to the parsed package, so that we can
5802 // update the package settings accordingly.
5803 pkg.cpuAbiOverride = cpuAbiOverride;
5805 if (DEBUG_ABI_SELECTION) {
5806 Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
5807 + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
5808 + pkg.applicationInfo.nativeLibraryRootRequiresIsa);
5811 // Push the derived path down into PackageSettings so we know what to
5812 // clean up at uninstall time.
5813 pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir;
5815 if (DEBUG_ABI_SELECTION) {
5816 Log.d(TAG, "Abis for package[" + pkg.packageName + "] are" +
5817 " primary=" + pkg.applicationInfo.primaryCpuAbi +
5818 " secondary=" + pkg.applicationInfo.secondaryCpuAbi);
5821 if ((scanFlags&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
5822 // We don't do this here during boot because we can do it all
5823 // at once after scanning all existing packages.
5825 // We also do this *before* we perform dexopt on this package, so that
5826 // we can avoid redundant dexopts, and also to make sure we've got the
5827 // code and package path correct.
5828 adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
5829 pkg, forceDex, (scanFlags & SCAN_DEFER_DEX) != 0);
5832 if ((scanFlags & SCAN_NO_DEX) == 0) {
5833 if (performDexOptLI(pkg, null /* instruction sets */, forceDex,
5834 (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) {
5835 throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI");
5839 if (mFactoryTest && pkg.requestedPermissions.contains(
5840 android.Manifest.permission.FACTORY_TEST)) {
5841 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
5844 ArrayList<PackageParser.Package> clientLibPkgs = null;
5847 synchronized (mPackages) {
5848 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5849 // Only system apps can add new shared libraries.
5850 if (pkg.libraryNames != null) {
5851 for (int i=0; i<pkg.libraryNames.size(); i++) {
5852 String name = pkg.libraryNames.get(i);
5853 boolean allowed = false;
5854 if (isUpdatedSystemApp(pkg)) {
5855 // New library entries can only be added through the
5856 // system image. This is important to get rid of a lot
5857 // of nasty edge cases: for example if we allowed a non-
5858 // system update of the app to add a library, then uninstalling
5859 // the update would make the library go away, and assumptions
5860 // we made such as through app install filtering would now
5861 // have allowed apps on the device which aren't compatible
5862 // with it. Better to just have the restriction here, be
5863 // conservative, and create many fewer cases that can negatively
5864 // impact the user experience.
5865 final PackageSetting sysPs = mSettings
5866 .getDisabledSystemPkgLPr(pkg.packageName);
5867 if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
5868 for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
5869 if (name.equals(sysPs.pkg.libraryNames.get(j))) {
5880 if (!mSharedLibraries.containsKey(name)) {
5881 mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
5882 } else if (!name.equals(pkg.packageName)) {
5883 Slog.w(TAG, "Package " + pkg.packageName + " library "
5884 + name + " already exists; skipping");
5887 Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
5888 + name + " that is not declared on system image; skipping");
5891 if ((scanFlags&SCAN_BOOTING) == 0) {
5892 // If we are not booting, we need to update any applications
5893 // that are clients of our shared library. If we are booting,
5894 // this will all be done once the scan is complete.
5895 clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
5901 // We also need to dexopt any apps that are dependent on this library. Note that
5902 // if these fail, we should abort the install since installing the library will
5903 // result in some apps being broken.
5904 if (clientLibPkgs != null) {
5905 if ((scanFlags & SCAN_NO_DEX) == 0) {
5906 for (int i = 0; i < clientLibPkgs.size(); i++) {
5907 PackageParser.Package clientPkg = clientLibPkgs.get(i);
5908 if (performDexOptLI(clientPkg, null /* instruction sets */, forceDex,
5909 (scanFlags & SCAN_DEFER_DEX) != 0, false) == DEX_OPT_FAILED) {
5910 throw new PackageManagerException(INSTALL_FAILED_DEXOPT,
5911 "scanPackageLI failed to dexopt clientLibPkgs");
5917 // Request the ActivityManager to kill the process(only for existing packages)
5918 // so that we do not end up in a confused state while the user is still using the older
5919 // version of the application while the new one gets installed.
5920 if ((scanFlags & SCAN_REPLACING) != 0) {
5921 killApplication(pkg.applicationInfo.packageName,
5922 pkg.applicationInfo.uid, "update pkg");
5925 // Also need to kill any apps that are dependent on the library.
5926 if (clientLibPkgs != null) {
5927 for (int i=0; i<clientLibPkgs.size(); i++) {
5928 PackageParser.Package clientPkg = clientLibPkgs.get(i);
5929 killApplication(clientPkg.applicationInfo.packageName,
5930 clientPkg.applicationInfo.uid, "update lib");
5935 synchronized (mPackages) {
5936 // We don't expect installation to fail beyond this point
5938 // Add the new setting to mSettings
5939 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
5940 // Add the new setting to mPackages
5941 mPackages.put(pkg.applicationInfo.packageName, pkg);
5942 // Make sure we don't accidentally delete its data.
5943 final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
5944 while (iter.hasNext()) {
5945 PackageCleanItem item = iter.next();
5946 if (pkgName.equals(item.packageName)) {
5951 // Take care of first install / last update times.
5952 if (currentTime != 0) {
5953 if (pkgSetting.firstInstallTime == 0) {
5954 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
5955 } else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
5956 pkgSetting.lastUpdateTime = currentTime;
5958 } else if (pkgSetting.firstInstallTime == 0) {
5959 // We need *something*. Take time time stamp of the file.
5960 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
5961 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
5962 if (scanFileTime != pkgSetting.timeStamp) {
5963 // A package on the system image has changed; consider this
5965 pkgSetting.lastUpdateTime = scanFileTime;
5969 // Add the package's KeySets to the global KeySetManagerService
5970 KeySetManagerService ksms = mSettings.mKeySetManagerService;
5972 // Old KeySetData no longer valid.
5973 ksms.removeAppKeySetDataLPw(pkg.packageName);
5974 ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys);
5975 if (pkg.mKeySetMapping != null) {
5976 for (Map.Entry<String, ArraySet<PublicKey>> entry :
5977 pkg.mKeySetMapping.entrySet()) {
5978 if (entry.getValue() != null) {
5979 ksms.addDefinedKeySetToPackageLPw(pkg.packageName,
5980 entry.getValue(), entry.getKey());
5983 if (pkg.mUpgradeKeySets != null) {
5984 for (String upgradeAlias : pkg.mUpgradeKeySets) {
5985 ksms.addUpgradeKeySetToPackageLPw(pkg.packageName, upgradeAlias);
5989 } catch (NullPointerException e) {
5990 Slog.e(TAG, "Could not add KeySet to " + pkg.packageName, e);
5991 } catch (IllegalArgumentException e) {
5992 Slog.e(TAG, "Could not add KeySet to malformed package" + pkg.packageName, e);
5995 int N = pkg.providers.size();
5996 StringBuilder r = null;
5998 for (i=0; i<N; i++) {
5999 PackageParser.Provider p = pkg.providers.get(i);
6000 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
6001 p.info.processName, pkg.applicationInfo.uid);
6002 mProviders.addProvider(p);
6003 p.syncable = p.info.isSyncable;
6004 if (p.info.authority != null) {
6005 String names[] = p.info.authority.split(";");
6006 p.info.authority = null;
6007 for (int j = 0; j < names.length; j++) {
6008 if (j == 1 && p.syncable) {
6009 // We only want the first authority for a provider to possibly be
6010 // syncable, so if we already added this provider using a different
6011 // authority clear the syncable flag. We copy the provider before
6012 // changing it because the mProviders object contains a reference
6013 // to a provider that we don't want to change.
6014 // Only do this for the second authority since the resulting provider
6015 // object can be the same for all future authorities for this provider.
6016 p = new PackageParser.Provider(p);
6019 if (!mProvidersByAuthority.containsKey(names[j])) {
6020 mProvidersByAuthority.put(names[j], p);
6021 if (p.info.authority == null) {
6022 p.info.authority = names[j];
6024 p.info.authority = p.info.authority + ";" + names[j];
6026 if (DEBUG_PACKAGE_SCANNING) {
6027 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
6028 Log.d(TAG, "Registered content provider: " + names[j]
6029 + ", className = " + p.info.name + ", isSyncable = "
6030 + p.info.isSyncable);
6033 PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
6034 Slog.w(TAG, "Skipping provider name " + names[j] +
6035 " (in package " + pkg.applicationInfo.packageName +
6036 "): name already used by "
6037 + ((other != null && other.getComponentName() != null)
6038 ? other.getComponentName().getPackageName() : "?"));
6042 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6044 r = new StringBuilder(256);
6048 r.append(p.info.name);
6052 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
6055 N = pkg.services.size();
6057 for (i=0; i<N; i++) {
6058 PackageParser.Service s = pkg.services.get(i);
6059 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
6060 s.info.processName, pkg.applicationInfo.uid);
6061 mServices.addService(s);
6062 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6064 r = new StringBuilder(256);
6068 r.append(s.info.name);
6072 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
6075 N = pkg.receivers.size();
6077 for (i=0; i<N; i++) {
6078 PackageParser.Activity a = pkg.receivers.get(i);
6079 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
6080 a.info.processName, pkg.applicationInfo.uid);
6081 mReceivers.addActivity(a, "receiver");
6082 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6084 r = new StringBuilder(256);
6088 r.append(a.info.name);
6092 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
6095 N = pkg.activities.size();
6097 for (i=0; i<N; i++) {
6098 PackageParser.Activity a = pkg.activities.get(i);
6099 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
6100 a.info.processName, pkg.applicationInfo.uid);
6101 mActivities.addActivity(a, "activity");
6102 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6104 r = new StringBuilder(256);
6108 r.append(a.info.name);
6112 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
6115 N = pkg.permissionGroups.size();
6117 for (i=0; i<N; i++) {
6118 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
6119 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
6121 mPermissionGroups.put(pg.info.name, pg);
6122 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6124 r = new StringBuilder(256);
6128 r.append(pg.info.name);
6131 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
6132 + pg.info.packageName + " ignored: original from "
6133 + cur.info.packageName);
6134 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6136 r = new StringBuilder(256);
6141 r.append(pg.info.name);
6146 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
6149 N = pkg.permissions.size();
6151 for (i=0; i<N; i++) {
6152 PackageParser.Permission p = pkg.permissions.get(i);
6153 ArrayMap<String, BasePermission> permissionMap =
6154 p.tree ? mSettings.mPermissionTrees
6155 : mSettings.mPermissions;
6156 p.group = mPermissionGroups.get(p.info.group);
6157 if (p.info.group == null || p.group != null) {
6158 BasePermission bp = permissionMap.get(p.info.name);
6160 // Allow system apps to redefine non-system permissions
6161 if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
6162 final boolean currentOwnerIsSystem = (bp.perm != null
6163 && isSystemApp(bp.perm.owner));
6164 if (isSystemApp(p.owner)) {
6165 if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
6166 // It's a built-in permission and no owner, take ownership now
6167 bp.packageSetting = pkgSetting;
6169 bp.uid = pkg.applicationInfo.uid;
6170 bp.sourcePackage = p.info.packageName;
6171 } else if (!currentOwnerIsSystem) {
6172 String msg = "New decl " + p.owner + " of permission "
6173 + p.info.name + " is system; overriding " + bp.sourcePackage;
6174 reportSettingsProblem(Log.WARN, msg);
6181 bp = new BasePermission(p.info.name, p.info.packageName,
6182 BasePermission.TYPE_NORMAL);
6183 permissionMap.put(p.info.name, bp);
6186 if (bp.perm == null) {
6187 if (bp.sourcePackage == null
6188 || bp.sourcePackage.equals(p.info.packageName)) {
6189 BasePermission tree = findPermissionTreeLP(p.info.name);
6191 || tree.sourcePackage.equals(p.info.packageName)) {
6192 bp.packageSetting = pkgSetting;
6194 bp.uid = pkg.applicationInfo.uid;
6195 bp.sourcePackage = p.info.packageName;
6196 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6198 r = new StringBuilder(256);
6202 r.append(p.info.name);
6205 Slog.w(TAG, "Permission " + p.info.name + " from package "
6206 + p.info.packageName + " ignored: base tree "
6207 + tree.name + " is from package "
6208 + tree.sourcePackage);
6211 Slog.w(TAG, "Permission " + p.info.name + " from package "
6212 + p.info.packageName + " ignored: original from "
6213 + bp.sourcePackage);
6215 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6217 r = new StringBuilder(256);
6222 r.append(p.info.name);
6225 bp.protectionLevel = p.info.protectionLevel;
6228 Slog.w(TAG, "Permission " + p.info.name + " from package "
6229 + p.info.packageName + " ignored: no group "
6234 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
6237 N = pkg.instrumentation.size();
6239 for (i=0; i<N; i++) {
6240 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
6241 a.info.packageName = pkg.applicationInfo.packageName;
6242 a.info.sourceDir = pkg.applicationInfo.sourceDir;
6243 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
6244 a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
6245 a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
6246 a.info.dataDir = pkg.applicationInfo.dataDir;
6248 // TODO: Update instrumentation.nativeLibraryDir as well ? Does it
6249 // need other information about the application, like the ABI and what not ?
6250 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
6251 mInstrumentation.put(a.getComponentName(), a);
6252 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
6254 r = new StringBuilder(256);
6258 r.append(a.info.name);
6262 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
6265 if (pkg.protectedBroadcasts != null) {
6266 N = pkg.protectedBroadcasts.size();
6267 for (i=0; i<N; i++) {
6268 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
6272 pkgSetting.setTimeStamp(scanFileTime);
6274 // Create idmap files for pairs of (packages, overlay packages).
6275 // Note: "android", ie framework-res.apk, is handled by native layers.
6276 if (pkg.mOverlayTarget != null) {
6277 // This is an overlay package.
6278 if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
6279 if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
6280 mOverlays.put(pkg.mOverlayTarget,
6281 new ArrayMap<String, PackageParser.Package>());
6283 ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
6284 map.put(pkg.packageName, pkg);
6285 PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
6286 if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
6287 throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
6288 "scanPackageLI failed to createIdmap");
6291 } else if (mOverlays.containsKey(pkg.packageName) &&
6292 !pkg.packageName.equals("android")) {
6293 // This is a regular package, with one or more known overlay packages.
6294 createIdmapsForPackageLI(pkg);
6302 * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
6303 * i.e, so that all packages can be run inside a single process if required.
6305 * Optionally, callers can pass in a parsed package via {@code newPackage} in which case
6306 * this function will either try and make the ABI for all packages in {@code packagesForUser}
6307 * match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match
6308 * the ABI selected for {@code packagesForUser}. This variant is used when installing or
6309 * updating a package that belongs to a shared user.
6311 * NOTE: We currently only match for the primary CPU abi string. Matching the secondary
6312 * adds unnecessary complexity.
6314 private void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
6315 PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) {
6316 String requiredInstructionSet = null;
6317 if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
6318 requiredInstructionSet = VMRuntime.getInstructionSet(
6319 scannedPackage.applicationInfo.primaryCpuAbi);
6322 PackageSetting requirer = null;
6323 for (PackageSetting ps : packagesForUser) {
6324 // If packagesForUser contains scannedPackage, we skip it. This will happen
6325 // when scannedPackage is an update of an existing package. Without this check,
6326 // we will never be able to change the ABI of any package belonging to a shared
6327 // user, even if it's compatible with other packages.
6328 if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
6329 if (ps.primaryCpuAbiString == null) {
6333 final String instructionSet = VMRuntime.getInstructionSet(ps.primaryCpuAbiString);
6334 if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) {
6335 // We have a mismatch between instruction sets (say arm vs arm64) warn about
6336 // this but there's not much we can do.
6337 String errorMessage = "Instruction set mismatch, "
6338 + ((requirer == null) ? "[caller]" : requirer)
6339 + " requires " + requiredInstructionSet + " whereas " + ps
6340 + " requires " + instructionSet;
6341 Slog.w(TAG, errorMessage);
6344 if (requiredInstructionSet == null) {
6345 requiredInstructionSet = instructionSet;
6351 if (requiredInstructionSet != null) {
6353 if (requirer != null) {
6354 // requirer != null implies that either scannedPackage was null or that scannedPackage
6355 // did not require an ABI, in which case we have to adjust scannedPackage to match
6356 // the ABI of the set (which is the same as requirer's ABI)
6357 adjustedAbi = requirer.primaryCpuAbiString;
6358 if (scannedPackage != null) {
6359 scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi;
6362 // requirer == null implies that we're updating all ABIs in the set to
6363 // match scannedPackage.
6364 adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi;
6367 for (PackageSetting ps : packagesForUser) {
6368 if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
6369 if (ps.primaryCpuAbiString != null) {
6373 ps.primaryCpuAbiString = adjustedAbi;
6374 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
6375 ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
6376 Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi);
6378 if (performDexOptLI(ps.pkg, null /* instruction sets */, forceDexOpt,
6379 deferDexOpt, true) == DEX_OPT_FAILED) {
6380 ps.primaryCpuAbiString = null;
6381 ps.pkg.applicationInfo.primaryCpuAbi = null;
6384 mInstaller.rmdex(ps.codePathString,
6385 getDexCodeInstructionSet(getPreferredInstructionSet()));
6393 private void setUpCustomResolverActivity(PackageParser.Package pkg) {
6394 synchronized (mPackages) {
6395 mResolverReplaced = true;
6396 // Set up information for custom user intent resolution activity.
6397 mResolveActivity.applicationInfo = pkg.applicationInfo;
6398 mResolveActivity.name = mCustomResolverComponentName.getClassName();
6399 mResolveActivity.packageName = pkg.applicationInfo.packageName;
6400 mResolveActivity.processName = null;
6401 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
6402 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
6403 ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
6404 mResolveActivity.theme = 0;
6405 mResolveActivity.exported = true;
6406 mResolveActivity.enabled = true;
6407 mResolveInfo.activityInfo = mResolveActivity;
6408 mResolveInfo.priority = 0;
6409 mResolveInfo.preferredOrder = 0;
6410 mResolveInfo.match = 0;
6411 mResolveComponentName = mCustomResolverComponentName;
6412 Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " +
6413 mResolveComponentName);
6417 private static String calculateBundledApkRoot(final String codePathString) {
6418 final File codePath = new File(codePathString);
6419 final File codeRoot;
6420 if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
6421 codeRoot = Environment.getRootDirectory();
6422 } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) {
6423 codeRoot = Environment.getOemDirectory();
6424 } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
6425 codeRoot = Environment.getVendorDirectory();
6427 // Unrecognized code path; take its top real segment as the apk root:
6428 // e.g. /something/app/blah.apk => /something
6430 File f = codePath.getCanonicalFile();
6431 File parent = f.getParentFile(); // non-null because codePath is a file
6433 while ((tmp = parent.getParentFile()) != null) {
6438 Slog.w(TAG, "Unrecognized code path "
6439 + codePath + " - using " + codeRoot);
6440 } catch (IOException e) {
6441 // Can't canonicalize the code path -- shenanigans?
6442 Slog.w(TAG, "Can't canonicalize code path " + codePath);
6443 return Environment.getRootDirectory().getPath();
6446 return codeRoot.getPath();
6450 * Derive and set the location of native libraries for the given package,
6451 * which varies depending on where and how the package was installed.
6453 private void setNativeLibraryPaths(PackageParser.Package pkg) {
6454 final ApplicationInfo info = pkg.applicationInfo;
6455 final String codePath = pkg.codePath;
6456 final File codeFile = new File(codePath);
6457 final boolean bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info);
6458 final boolean asecApp = isForwardLocked(info) || isExternal(info);
6460 info.nativeLibraryRootDir = null;
6461 info.nativeLibraryRootRequiresIsa = false;
6462 info.nativeLibraryDir = null;
6463 info.secondaryNativeLibraryDir = null;
6465 if (isApkFile(codeFile)) {
6466 // Monolithic install
6468 // If "/system/lib64/apkname" exists, assume that is the per-package
6469 // native library directory to use; otherwise use "/system/lib/apkname".
6470 final String apkRoot = calculateBundledApkRoot(info.sourceDir);
6471 final boolean is64Bit = VMRuntime.is64BitInstructionSet(
6472 getPrimaryInstructionSet(info));
6474 // This is a bundled system app so choose the path based on the ABI.
6475 // if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this
6476 // is just the default path.
6477 final String apkName = deriveCodePathName(codePath);
6478 final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
6479 info.nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir,
6480 apkName).getAbsolutePath();
6482 if (info.secondaryCpuAbi != null) {
6483 final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME;
6484 info.secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot),
6485 secondaryLibDir, apkName).getAbsolutePath();
6487 } else if (asecApp) {
6488 info.nativeLibraryRootDir = new File(codeFile.getParentFile(), LIB_DIR_NAME)
6491 final String apkName = deriveCodePathName(codePath);
6492 info.nativeLibraryRootDir = new File(mAppLib32InstallDir, apkName)
6496 info.nativeLibraryRootRequiresIsa = false;
6497 info.nativeLibraryDir = info.nativeLibraryRootDir;
6500 info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
6501 info.nativeLibraryRootRequiresIsa = true;
6503 info.nativeLibraryDir = new File(info.nativeLibraryRootDir,
6504 getPrimaryInstructionSet(info)).getAbsolutePath();
6506 if (info.secondaryCpuAbi != null) {
6507 info.secondaryNativeLibraryDir = new File(info.nativeLibraryRootDir,
6508 VMRuntime.getInstructionSet(info.secondaryCpuAbi)).getAbsolutePath();
6514 * Calculate the abis and roots for a bundled app. These can uniquely
6515 * be determined from the contents of the system partition, i.e whether
6516 * it contains 64 or 32 bit shared libraries etc. We do not validate any
6517 * of this information, and instead assume that the system was built
6520 private void setBundledAppAbisAndRoots(PackageParser.Package pkg,
6521 PackageSetting pkgSetting) {
6522 final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
6524 // If "/system/lib64/apkname" exists, assume that is the per-package
6525 // native library directory to use; otherwise use "/system/lib/apkname".
6526 final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir);
6527 setBundledAppAbi(pkg, apkRoot, apkName);
6528 // pkgSetting might be null during rescan following uninstall of updates
6529 // to a bundled app, so accommodate that possibility. The settings in
6530 // that case will be established later from the parsed package.
6532 // If the settings aren't null, sync them up with what we've just derived.
6533 // note that apkRoot isn't stored in the package settings.
6534 if (pkgSetting != null) {
6535 pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
6536 pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
6541 * Deduces the ABI of a bundled app and sets the relevant fields on the
6542 * parsed pkg object.
6544 * @param apkRoot the root of the installed apk, something like {@code /system} or {@code /oem}
6545 * under which system libraries are installed.
6546 * @param apkName the name of the installed package.
6548 private static void setBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) {
6549 final File codeFile = new File(pkg.codePath);
6551 final boolean has64BitLibs;
6552 final boolean has32BitLibs;
6553 if (isApkFile(codeFile)) {
6554 // Monolithic install
6555 has64BitLibs = (new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath())).exists();
6556 has32BitLibs = (new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath())).exists();
6559 final File rootDir = new File(codeFile, LIB_DIR_NAME);
6560 if (!ArrayUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS)
6561 && !TextUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS[0])) {
6562 final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_64_BIT_ABIS[0]);
6563 has64BitLibs = (new File(rootDir, isa)).exists();
6565 has64BitLibs = false;
6567 if (!ArrayUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS)
6568 && !TextUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS[0])) {
6569 final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_32_BIT_ABIS[0]);
6570 has32BitLibs = (new File(rootDir, isa)).exists();
6572 has32BitLibs = false;
6576 if (has64BitLibs && !has32BitLibs) {
6577 // The package has 64 bit libs, but not 32 bit libs. Its primary
6578 // ABI should be 64 bit. We can safely assume here that the bundled
6579 // native libraries correspond to the most preferred ABI in the list.
6581 pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
6582 pkg.applicationInfo.secondaryCpuAbi = null;
6583 } else if (has32BitLibs && !has64BitLibs) {
6584 // The package has 32 bit libs but not 64 bit libs. Its primary
6585 // ABI should be 32 bit.
6587 pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
6588 pkg.applicationInfo.secondaryCpuAbi = null;
6589 } else if (has32BitLibs && has64BitLibs) {
6590 // The application has both 64 and 32 bit bundled libraries. We check
6591 // here that the app declares multiArch support, and warn if it doesn't.
6593 // We will be lenient here and record both ABIs. The primary will be the
6594 // ABI that's higher on the list, i.e, a device that's configured to prefer
6595 // 64 bit apps will see a 64 bit primary ABI,
6597 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) {
6598 Slog.e(TAG, "Package: " + pkg + " has multiple bundled libs, but is not multiarch.");
6601 if (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) {
6602 pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
6603 pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
6605 pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
6606 pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
6609 pkg.applicationInfo.primaryCpuAbi = null;
6610 pkg.applicationInfo.secondaryCpuAbi = null;
6614 private void killApplication(String pkgName, int appId, String reason) {
6615 // Request the ActivityManager to kill the process(only for existing packages)
6616 // so that we do not end up in a confused state while the user is still using the older
6617 // version of the application while the new one gets installed.
6618 IActivityManager am = ActivityManagerNative.getDefault();
6621 am.killApplicationWithAppId(pkgName, appId, reason);
6622 } catch (RemoteException e) {
6627 void removePackageLI(PackageSetting ps, boolean chatty) {
6628 if (DEBUG_INSTALL) {
6630 Log.d(TAG, "Removing package " + ps.name);
6634 synchronized (mPackages) {
6635 mPackages.remove(ps.name);
6636 final PackageParser.Package pkg = ps.pkg;
6638 cleanPackageDataStructuresLILPw(pkg, chatty);
6643 void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
6644 if (DEBUG_INSTALL) {
6646 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
6650 synchronized (mPackages) {
6651 mPackages.remove(pkg.applicationInfo.packageName);
6652 cleanPackageDataStructuresLILPw(pkg, chatty);
6656 void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
6657 int N = pkg.providers.size();
6658 StringBuilder r = null;
6660 for (i=0; i<N; i++) {
6661 PackageParser.Provider p = pkg.providers.get(i);
6662 mProviders.removeProvider(p);
6663 if (p.info.authority == null) {
6665 /* There was another ContentProvider with this authority when
6666 * this app was installed so this authority is null,
6667 * Ignore it as we don't have to unregister the provider.
6671 String names[] = p.info.authority.split(";");
6672 for (int j = 0; j < names.length; j++) {
6673 if (mProvidersByAuthority.get(names[j]) == p) {
6674 mProvidersByAuthority.remove(names[j]);
6677 Log.d(TAG, "Unregistered content provider: " + names[j]
6678 + ", className = " + p.info.name + ", isSyncable = "
6679 + p.info.isSyncable);
6683 if (DEBUG_REMOVE && chatty) {
6685 r = new StringBuilder(256);
6689 r.append(p.info.name);
6693 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
6696 N = pkg.services.size();
6698 for (i=0; i<N; i++) {
6699 PackageParser.Service s = pkg.services.get(i);
6700 mServices.removeService(s);
6703 r = new StringBuilder(256);
6707 r.append(s.info.name);
6711 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
6714 N = pkg.receivers.size();
6716 for (i=0; i<N; i++) {
6717 PackageParser.Activity a = pkg.receivers.get(i);
6718 mReceivers.removeActivity(a, "receiver");
6719 if (DEBUG_REMOVE && chatty) {
6721 r = new StringBuilder(256);
6725 r.append(a.info.name);
6729 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
6732 N = pkg.activities.size();
6734 for (i=0; i<N; i++) {
6735 PackageParser.Activity a = pkg.activities.get(i);
6736 mActivities.removeActivity(a, "activity");
6737 if (DEBUG_REMOVE && chatty) {
6739 r = new StringBuilder(256);
6743 r.append(a.info.name);
6747 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
6750 N = pkg.permissions.size();
6752 for (i=0; i<N; i++) {
6753 PackageParser.Permission p = pkg.permissions.get(i);
6754 BasePermission bp = mSettings.mPermissions.get(p.info.name);
6756 bp = mSettings.mPermissionTrees.get(p.info.name);
6758 if (bp != null && bp.perm == p) {
6760 if (DEBUG_REMOVE && chatty) {
6762 r = new StringBuilder(256);
6766 r.append(p.info.name);
6769 if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
6770 ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(p.info.name);
6771 if (appOpPerms != null) {
6772 appOpPerms.remove(pkg.packageName);
6777 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
6780 N = pkg.requestedPermissions.size();
6782 for (i=0; i<N; i++) {
6783 String perm = pkg.requestedPermissions.get(i);
6784 BasePermission bp = mSettings.mPermissions.get(perm);
6785 if (bp != null && (bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
6786 ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(perm);
6787 if (appOpPerms != null) {
6788 appOpPerms.remove(pkg.packageName);
6789 if (appOpPerms.isEmpty()) {
6790 mAppOpPermissionPackages.remove(perm);
6796 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
6799 N = pkg.instrumentation.size();
6801 for (i=0; i<N; i++) {
6802 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
6803 mInstrumentation.remove(a.getComponentName());
6804 if (DEBUG_REMOVE && chatty) {
6806 r = new StringBuilder(256);
6810 r.append(a.info.name);
6814 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
6818 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6819 // Only system apps can hold shared libraries.
6820 if (pkg.libraryNames != null) {
6821 for (i=0; i<pkg.libraryNames.size(); i++) {
6822 String name = pkg.libraryNames.get(i);
6823 SharedLibraryEntry cur = mSharedLibraries.get(name);
6824 if (cur != null && cur.apk != null && cur.apk.equals(pkg.packageName)) {
6825 mSharedLibraries.remove(name);
6826 if (DEBUG_REMOVE && chatty) {
6828 r = new StringBuilder(256);
6839 if (DEBUG_REMOVE) Log.d(TAG, " Libraries: " + r);
6843 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
6844 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
6845 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
6852 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
6853 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
6854 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
6856 private void updatePermissionsLPw(String changingPkg,
6857 PackageParser.Package pkgInfo, int flags) {
6858 // Make sure there are no dangling permission trees.
6859 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
6860 while (it.hasNext()) {
6861 final BasePermission bp = it.next();
6862 if (bp.packageSetting == null) {
6863 // We may not yet have parsed the package, so just see if
6864 // we still know about its settings.
6865 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
6867 if (bp.packageSetting == null) {
6868 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
6869 + " from package " + bp.sourcePackage);
6871 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
6872 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
6873 Slog.i(TAG, "Removing old permission tree: " + bp.name
6874 + " from package " + bp.sourcePackage);
6875 flags |= UPDATE_PERMISSIONS_ALL;
6881 // Make sure all dynamic permissions have been assigned to a package,
6882 // and make sure there are no dangling permissions.
6883 it = mSettings.mPermissions.values().iterator();
6884 while (it.hasNext()) {
6885 final BasePermission bp = it.next();
6886 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6887 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
6888 + bp.name + " pkg=" + bp.sourcePackage
6889 + " info=" + bp.pendingInfo);
6890 if (bp.packageSetting == null && bp.pendingInfo != null) {
6891 final BasePermission tree = findPermissionTreeLP(bp.name);
6892 if (tree != null && tree.perm != null) {
6893 bp.packageSetting = tree.packageSetting;
6894 bp.perm = new PackageParser.Permission(tree.perm.owner,
6895 new PermissionInfo(bp.pendingInfo));
6896 bp.perm.info.packageName = tree.perm.info.packageName;
6897 bp.perm.info.name = bp.name;
6902 if (bp.packageSetting == null) {
6903 // We may not yet have parsed the package, so just see if
6904 // we still know about its settings.
6905 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
6907 if (bp.packageSetting == null) {
6908 Slog.w(TAG, "Removing dangling permission: " + bp.name
6909 + " from package " + bp.sourcePackage);
6911 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
6912 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
6913 Slog.i(TAG, "Removing old permission: " + bp.name
6914 + " from package " + bp.sourcePackage);
6915 flags |= UPDATE_PERMISSIONS_ALL;
6921 // Now update the permissions for all packages, in particular
6922 // replace the granted permissions of the system packages.
6923 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
6924 for (PackageParser.Package pkg : mPackages.values()) {
6925 if (pkg != pkgInfo) {
6926 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0,
6932 if (pkgInfo != null) {
6933 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0, changingPkg);
6937 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
6938 String packageOfInterest) {
6939 final PackageSetting ps = (PackageSetting) pkg.mExtras;
6943 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
6944 ArraySet<String> origPermissions = gp.grantedPermissions;
6945 boolean changedPermission = false;
6948 ps.permissionsFixed = false;
6950 origPermissions = new ArraySet<String>(gp.grantedPermissions);
6951 gp.grantedPermissions.clear();
6952 gp.gids = mGlobalGids;
6956 if (gp.gids == null) {
6957 gp.gids = mGlobalGids;
6960 final int N = pkg.requestedPermissions.size();
6961 for (int i=0; i<N; i++) {
6962 final String name = pkg.requestedPermissions.get(i);
6963 final boolean required = pkg.requestedPermissionsRequired.get(i);
6964 final BasePermission bp = mSettings.mPermissions.get(name);
6965 if (DEBUG_INSTALL) {
6967 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
6971 if (bp == null || bp.packageSetting == null) {
6972 if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
6973 Slog.w(TAG, "Unknown permission " + name
6974 + " in package " + pkg.packageName);
6979 final String perm = bp.name;
6981 boolean allowedSig = false;
6982 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
6983 // Keep track of app op permissions.
6984 ArraySet<String> pkgs = mAppOpPermissionPackages.get(bp.name);
6986 pkgs = new ArraySet<>();
6987 mAppOpPermissionPackages.put(bp.name, pkgs);
6989 pkgs.add(pkg.packageName);
6991 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
6992 if (level == PermissionInfo.PROTECTION_NORMAL
6993 || level == PermissionInfo.PROTECTION_DANGEROUS) {
6994 // We grant a normal or dangerous permission if any of the following
6996 // 1) The permission is required
6997 // 2) The permission is optional, but was granted in the past
6998 // 3) The permission is optional, but was requested by an
6999 // app in /system (not /data)
7001 // Otherwise, reject the permission.
7002 allowed = (required || origPermissions.contains(perm)
7003 || (isSystemApp(ps) && !isUpdatedSystemApp(ps)));
7004 } else if (bp.packageSetting == null) {
7005 // This permission is invalid; skip it.
7007 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
7008 allowed = grantSignaturePermission(perm, pkg, bp, origPermissions);
7015 if (DEBUG_INSTALL) {
7017 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
7021 if (!isSystemApp(ps) && ps.permissionsFixed) {
7022 // If this is an existing, non-system package, then
7023 // we can't add any new permissions to it.
7024 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
7025 // Except... if this is a permission that was added
7026 // to the platform (note: need to only do this when
7027 // updating the platform).
7028 allowed = isNewPlatformPermissionForPackage(perm, pkg);
7032 if (!gp.grantedPermissions.contains(perm)) {
7033 changedPermission = true;
7034 gp.grantedPermissions.add(perm);
7035 gp.gids = appendInts(gp.gids, bp.gids);
7036 } else if (!ps.haveGids) {
7037 gp.gids = appendInts(gp.gids, bp.gids);
7040 if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
7041 Slog.w(TAG, "Not granting permission " + perm
7042 + " to package " + pkg.packageName
7043 + " because it was previously installed without");
7047 if (gp.grantedPermissions.remove(perm)) {
7048 changedPermission = true;
7049 gp.gids = removeInts(gp.gids, bp.gids);
7050 Slog.i(TAG, "Un-granting permission " + perm
7051 + " from package " + pkg.packageName
7052 + " (protectionLevel=" + bp.protectionLevel
7053 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
7055 } else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
7056 // Don't print warning for app op permissions, since it is fine for them
7057 // not to be granted, there is a UI for the user to decide.
7058 if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
7059 Slog.w(TAG, "Not granting permission " + perm
7060 + " to package " + pkg.packageName
7061 + " (protectionLevel=" + bp.protectionLevel
7062 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
7069 if ((changedPermission || replace) && !ps.permissionsFixed &&
7070 !isSystemApp(ps) || isUpdatedSystemApp(ps)){
7071 // This is the first that we have heard about this package, so the
7072 // permissions we have now selected are fixed until explicitly
7074 ps.permissionsFixed = true;
7079 private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
7080 boolean allowed = false;
7081 final int NP = PackageParser.NEW_PERMISSIONS.length;
7082 for (int ip=0; ip<NP; ip++) {
7083 final PackageParser.NewPermissionInfo npi
7084 = PackageParser.NEW_PERMISSIONS[ip];
7085 if (npi.name.equals(perm)
7086 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
7088 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
7096 private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
7097 BasePermission bp, ArraySet<String> origPermissions) {
7099 allowed = (compareSignatures(
7100 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
7101 == PackageManager.SIGNATURE_MATCH)
7102 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
7103 == PackageManager.SIGNATURE_MATCH);
7104 if (!allowed && (bp.protectionLevel
7105 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
7106 if (isSystemApp(pkg)) {
7107 // For updated system applications, a system permission
7108 // is granted only if it had been defined by the original application.
7109 if (isUpdatedSystemApp(pkg)) {
7110 final PackageSetting sysPs = mSettings
7111 .getDisabledSystemPkgLPr(pkg.packageName);
7112 final GrantedPermissions origGp = sysPs.sharedUser != null
7113 ? sysPs.sharedUser : sysPs;
7115 if (origGp.grantedPermissions.contains(perm)) {
7116 // If the original was granted this permission, we take
7117 // that grant decision as read and propagate it to the
7121 // The system apk may have been updated with an older
7122 // version of the one on the data partition, but which
7123 // granted a new system permission that it didn't have
7124 // before. In this case we do want to allow the app to
7125 // now get the new permission if the ancestral apk is
7126 // privileged to get it.
7127 if (sysPs.pkg != null && sysPs.isPrivileged()) {
7129 j<sysPs.pkg.requestedPermissions.size(); j++) {
7131 sysPs.pkg.requestedPermissions.get(j))) {
7139 allowed = isPrivilegedApp(pkg);
7143 if (!allowed && (bp.protectionLevel
7144 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
7145 // For development permissions, a development permission
7146 // is granted only if it was already granted.
7147 allowed = origPermissions.contains(perm);
7152 final class ActivityIntentResolver
7153 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
7154 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
7155 boolean defaultOnly, int userId) {
7156 if (!sUserManager.exists(userId)) return null;
7157 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
7158 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
7161 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
7163 if (!sUserManager.exists(userId)) return null;
7165 return super.queryIntent(intent, resolvedType,
7166 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
7169 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
7170 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
7171 if (!sUserManager.exists(userId)) return null;
7172 if (packageActivities == null) {
7176 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
7177 final int N = packageActivities.size();
7178 ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
7179 new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
7181 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
7182 for (int i = 0; i < N; ++i) {
7183 intentFilters = packageActivities.get(i).intents;
7184 if (intentFilters != null && intentFilters.size() > 0) {
7185 PackageParser.ActivityIntentInfo[] array =
7186 new PackageParser.ActivityIntentInfo[intentFilters.size()];
7187 intentFilters.toArray(array);
7191 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
7194 public final void addActivity(PackageParser.Activity a, String type) {
7195 final boolean systemApp = isSystemApp(a.info.applicationInfo);
7196 mActivities.put(a.getComponentName(), a);
7197 if (DEBUG_SHOW_INFO)
7199 TAG, " " + type + " " +
7200 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
7201 if (DEBUG_SHOW_INFO)
7202 Log.v(TAG, " Class=" + a.info.name);
7203 final int NI = a.intents.size();
7204 for (int j=0; j<NI; j++) {
7205 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
7206 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
7207 intent.setPriority(0);
7208 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
7209 + a.className + " with priority > 0, forcing to 0");
7211 if (DEBUG_SHOW_INFO) {
7212 Log.v(TAG, " IntentFilter:");
7213 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
7215 if (!intent.debugCheck()) {
7216 Log.w(TAG, "==> For Activity " + a.info.name);
7222 public final void removeActivity(PackageParser.Activity a, String type) {
7223 mActivities.remove(a.getComponentName());
7224 if (DEBUG_SHOW_INFO) {
7225 Log.v(TAG, " " + type + " "
7226 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
7227 : a.info.name) + ":");
7228 Log.v(TAG, " Class=" + a.info.name);
7230 final int NI = a.intents.size();
7231 for (int j=0; j<NI; j++) {
7232 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
7233 if (DEBUG_SHOW_INFO) {
7234 Log.v(TAG, " IntentFilter:");
7235 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
7237 removeFilter(intent);
7242 protected boolean allowFilterResult(
7243 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
7244 ActivityInfo filterAi = filter.activity.info;
7245 for (int i=dest.size()-1; i>=0; i--) {
7246 ActivityInfo destAi = dest.get(i).activityInfo;
7247 if (destAi.name == filterAi.name
7248 && destAi.packageName == filterAi.packageName) {
7256 protected ActivityIntentInfo[] newArray(int size) {
7257 return new ActivityIntentInfo[size];
7261 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
7262 if (!sUserManager.exists(userId)) return true;
7263 PackageParser.Package p = filter.activity.owner;
7265 PackageSetting ps = (PackageSetting)p.mExtras;
7267 // System apps are never considered stopped for purposes of
7268 // filtering, because there may be no way for the user to
7269 // actually re-launch them.
7270 return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
7271 && ps.getStopped(userId);
7278 protected boolean isPackageForFilter(String packageName,
7279 PackageParser.ActivityIntentInfo info) {
7280 return packageName.equals(info.activity.owner.packageName);
7284 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
7285 int match, int userId) {
7286 if (!sUserManager.exists(userId)) return null;
7287 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
7290 final PackageParser.Activity activity = info.activity;
7291 if (mSafeMode && (activity.info.applicationInfo.flags
7292 &ApplicationInfo.FLAG_SYSTEM) == 0) {
7295 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
7299 ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
7300 ps.readUserState(userId), userId);
7304 final ResolveInfo res = new ResolveInfo();
7305 res.activityInfo = ai;
7306 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
7309 res.priority = info.getPriority();
7310 res.preferredOrder = activity.owner.mPreferredOrder;
7311 //System.out.println("Result: " + res.activityInfo.className +
7312 // " = " + res.priority);
7314 res.isDefault = info.hasDefault;
7315 res.labelRes = info.labelRes;
7316 res.nonLocalizedLabel = info.nonLocalizedLabel;
7317 if (userNeedsBadging(userId)) {
7318 res.noResourceId = true;
7320 res.icon = info.icon;
7322 res.system = isSystemApp(res.activityInfo.applicationInfo);
7327 protected void sortResults(List<ResolveInfo> results) {
7328 Collections.sort(results, mResolvePrioritySorter);
7332 protected void dumpFilter(PrintWriter out, String prefix,
7333 PackageParser.ActivityIntentInfo filter) {
7334 out.print(prefix); out.print(
7335 Integer.toHexString(System.identityHashCode(filter.activity)));
7337 filter.activity.printComponentShortName(out);
7338 out.print(" filter ");
7339 out.println(Integer.toHexString(System.identityHashCode(filter)));
7342 // List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
7343 // final Iterator<ResolveInfo> i = resolveInfoList.iterator();
7344 // final List<ResolveInfo> retList = Lists.newArrayList();
7345 // while (i.hasNext()) {
7346 // final ResolveInfo resolveInfo = i.next();
7347 // if (isEnabledLP(resolveInfo.activityInfo)) {
7348 // retList.add(resolveInfo);
7354 // Keys are String (activity class name), values are Activity.
7355 private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
7356 = new ArrayMap<ComponentName, PackageParser.Activity>();
7360 private final class ServiceIntentResolver
7361 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
7362 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
7363 boolean defaultOnly, int userId) {
7364 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
7365 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
7368 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
7370 if (!sUserManager.exists(userId)) return null;
7372 return super.queryIntent(intent, resolvedType,
7373 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
7376 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
7377 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
7378 if (!sUserManager.exists(userId)) return null;
7379 if (packageServices == null) {
7383 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
7384 final int N = packageServices.size();
7385 ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
7386 new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
7388 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
7389 for (int i = 0; i < N; ++i) {
7390 intentFilters = packageServices.get(i).intents;
7391 if (intentFilters != null && intentFilters.size() > 0) {
7392 PackageParser.ServiceIntentInfo[] array =
7393 new PackageParser.ServiceIntentInfo[intentFilters.size()];
7394 intentFilters.toArray(array);
7398 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
7401 public final void addService(PackageParser.Service s) {
7402 mServices.put(s.getComponentName(), s);
7403 if (DEBUG_SHOW_INFO) {
7405 + (s.info.nonLocalizedLabel != null
7406 ? s.info.nonLocalizedLabel : s.info.name) + ":");
7407 Log.v(TAG, " Class=" + s.info.name);
7409 final int NI = s.intents.size();
7411 for (j=0; j<NI; j++) {
7412 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
7413 if (DEBUG_SHOW_INFO) {
7414 Log.v(TAG, " IntentFilter:");
7415 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
7417 if (!intent.debugCheck()) {
7418 Log.w(TAG, "==> For Service " + s.info.name);
7424 public final void removeService(PackageParser.Service s) {
7425 mServices.remove(s.getComponentName());
7426 if (DEBUG_SHOW_INFO) {
7427 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
7428 ? s.info.nonLocalizedLabel : s.info.name) + ":");
7429 Log.v(TAG, " Class=" + s.info.name);
7431 final int NI = s.intents.size();
7433 for (j=0; j<NI; j++) {
7434 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
7435 if (DEBUG_SHOW_INFO) {
7436 Log.v(TAG, " IntentFilter:");
7437 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
7439 removeFilter(intent);
7444 protected boolean allowFilterResult(
7445 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
7446 ServiceInfo filterSi = filter.service.info;
7447 for (int i=dest.size()-1; i>=0; i--) {
7448 ServiceInfo destAi = dest.get(i).serviceInfo;
7449 if (destAi.name == filterSi.name
7450 && destAi.packageName == filterSi.packageName) {
7458 protected PackageParser.ServiceIntentInfo[] newArray(int size) {
7459 return new PackageParser.ServiceIntentInfo[size];
7463 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
7464 if (!sUserManager.exists(userId)) return true;
7465 PackageParser.Package p = filter.service.owner;
7467 PackageSetting ps = (PackageSetting)p.mExtras;
7469 // System apps are never considered stopped for purposes of
7470 // filtering, because there may be no way for the user to
7471 // actually re-launch them.
7472 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
7473 && ps.getStopped(userId);
7480 protected boolean isPackageForFilter(String packageName,
7481 PackageParser.ServiceIntentInfo info) {
7482 return packageName.equals(info.service.owner.packageName);
7486 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
7487 int match, int userId) {
7488 if (!sUserManager.exists(userId)) return null;
7489 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
7490 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
7493 final PackageParser.Service service = info.service;
7494 if (mSafeMode && (service.info.applicationInfo.flags
7495 &ApplicationInfo.FLAG_SYSTEM) == 0) {
7498 PackageSetting ps = (PackageSetting) service.owner.mExtras;
7502 ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
7503 ps.readUserState(userId), userId);
7507 final ResolveInfo res = new ResolveInfo();
7508 res.serviceInfo = si;
7509 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
7510 res.filter = filter;
7512 res.priority = info.getPriority();
7513 res.preferredOrder = service.owner.mPreferredOrder;
7514 //System.out.println("Result: " + res.activityInfo.className +
7515 // " = " + res.priority);
7517 res.isDefault = info.hasDefault;
7518 res.labelRes = info.labelRes;
7519 res.nonLocalizedLabel = info.nonLocalizedLabel;
7520 res.icon = info.icon;
7521 res.system = isSystemApp(res.serviceInfo.applicationInfo);
7526 protected void sortResults(List<ResolveInfo> results) {
7527 Collections.sort(results, mResolvePrioritySorter);
7531 protected void dumpFilter(PrintWriter out, String prefix,
7532 PackageParser.ServiceIntentInfo filter) {
7533 out.print(prefix); out.print(
7534 Integer.toHexString(System.identityHashCode(filter.service)));
7536 filter.service.printComponentShortName(out);
7537 out.print(" filter ");
7538 out.println(Integer.toHexString(System.identityHashCode(filter)));
7541 // List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
7542 // final Iterator<ResolveInfo> i = resolveInfoList.iterator();
7543 // final List<ResolveInfo> retList = Lists.newArrayList();
7544 // while (i.hasNext()) {
7545 // final ResolveInfo resolveInfo = (ResolveInfo) i;
7546 // if (isEnabledLP(resolveInfo.serviceInfo)) {
7547 // retList.add(resolveInfo);
7553 // Keys are String (activity class name), values are Activity.
7554 private final ArrayMap<ComponentName, PackageParser.Service> mServices
7555 = new ArrayMap<ComponentName, PackageParser.Service>();
7559 private final class ProviderIntentResolver
7560 extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
7561 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
7562 boolean defaultOnly, int userId) {
7563 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
7564 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
7567 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
7569 if (!sUserManager.exists(userId))
7572 return super.queryIntent(intent, resolvedType,
7573 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
7576 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
7577 int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) {
7578 if (!sUserManager.exists(userId))
7580 if (packageProviders == null) {
7584 final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
7585 final int N = packageProviders.size();
7586 ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
7587 new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
7589 ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
7590 for (int i = 0; i < N; ++i) {
7591 intentFilters = packageProviders.get(i).intents;
7592 if (intentFilters != null && intentFilters.size() > 0) {
7593 PackageParser.ProviderIntentInfo[] array =
7594 new PackageParser.ProviderIntentInfo[intentFilters.size()];
7595 intentFilters.toArray(array);
7599 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
7602 public final void addProvider(PackageParser.Provider p) {
7603 if (mProviders.containsKey(p.getComponentName())) {
7604 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
7608 mProviders.put(p.getComponentName(), p);
7609 if (DEBUG_SHOW_INFO) {
7611 + (p.info.nonLocalizedLabel != null
7612 ? p.info.nonLocalizedLabel : p.info.name) + ":");
7613 Log.v(TAG, " Class=" + p.info.name);
7615 final int NI = p.intents.size();
7617 for (j = 0; j < NI; j++) {
7618 PackageParser.ProviderIntentInfo intent = p.intents.get(j);
7619 if (DEBUG_SHOW_INFO) {
7620 Log.v(TAG, " IntentFilter:");
7621 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
7623 if (!intent.debugCheck()) {
7624 Log.w(TAG, "==> For Provider " + p.info.name);
7630 public final void removeProvider(PackageParser.Provider p) {
7631 mProviders.remove(p.getComponentName());
7632 if (DEBUG_SHOW_INFO) {
7633 Log.v(TAG, " " + (p.info.nonLocalizedLabel != null
7634 ? p.info.nonLocalizedLabel : p.info.name) + ":");
7635 Log.v(TAG, " Class=" + p.info.name);
7637 final int NI = p.intents.size();
7639 for (j = 0; j < NI; j++) {
7640 PackageParser.ProviderIntentInfo intent = p.intents.get(j);
7641 if (DEBUG_SHOW_INFO) {
7642 Log.v(TAG, " IntentFilter:");
7643 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
7645 removeFilter(intent);
7650 protected boolean allowFilterResult(
7651 PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
7652 ProviderInfo filterPi = filter.provider.info;
7653 for (int i = dest.size() - 1; i >= 0; i--) {
7654 ProviderInfo destPi = dest.get(i).providerInfo;
7655 if (destPi.name == filterPi.name
7656 && destPi.packageName == filterPi.packageName) {
7664 protected PackageParser.ProviderIntentInfo[] newArray(int size) {
7665 return new PackageParser.ProviderIntentInfo[size];
7669 protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
7670 if (!sUserManager.exists(userId))
7672 PackageParser.Package p = filter.provider.owner;
7674 PackageSetting ps = (PackageSetting) p.mExtras;
7676 // System apps are never considered stopped for purposes of
7677 // filtering, because there may be no way for the user to
7678 // actually re-launch them.
7679 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
7680 && ps.getStopped(userId);
7687 protected boolean isPackageForFilter(String packageName,
7688 PackageParser.ProviderIntentInfo info) {
7689 return packageName.equals(info.provider.owner.packageName);
7693 protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
7694 int match, int userId) {
7695 if (!sUserManager.exists(userId))
7697 final PackageParser.ProviderIntentInfo info = filter;
7698 if (!mSettings.isEnabledLPr(info.provider.info, mFlags, userId)) {
7701 final PackageParser.Provider provider = info.provider;
7702 if (mSafeMode && (provider.info.applicationInfo.flags
7703 & ApplicationInfo.FLAG_SYSTEM) == 0) {
7706 PackageSetting ps = (PackageSetting) provider.owner.mExtras;
7710 ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
7711 ps.readUserState(userId), userId);
7715 final ResolveInfo res = new ResolveInfo();
7716 res.providerInfo = pi;
7717 if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
7718 res.filter = filter;
7720 res.priority = info.getPriority();
7721 res.preferredOrder = provider.owner.mPreferredOrder;
7723 res.isDefault = info.hasDefault;
7724 res.labelRes = info.labelRes;
7725 res.nonLocalizedLabel = info.nonLocalizedLabel;
7726 res.icon = info.icon;
7727 res.system = isSystemApp(res.providerInfo.applicationInfo);
7732 protected void sortResults(List<ResolveInfo> results) {
7733 Collections.sort(results, mResolvePrioritySorter);
7737 protected void dumpFilter(PrintWriter out, String prefix,
7738 PackageParser.ProviderIntentInfo filter) {
7741 Integer.toHexString(System.identityHashCode(filter.provider)));
7743 filter.provider.printComponentShortName(out);
7744 out.print(" filter ");
7745 out.println(Integer.toHexString(System.identityHashCode(filter)));
7748 private final ArrayMap<ComponentName, PackageParser.Provider> mProviders
7749 = new ArrayMap<ComponentName, PackageParser.Provider>();
7753 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
7754 new Comparator<ResolveInfo>() {
7755 public int compare(ResolveInfo r1, ResolveInfo r2) {
7756 int v1 = r1.priority;
7757 int v2 = r2.priority;
7758 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
7760 return (v1 > v2) ? -1 : 1;
7762 v1 = r1.preferredOrder;
7763 v2 = r2.preferredOrder;
7765 return (v1 > v2) ? -1 : 1;
7767 if (r1.isDefault != r2.isDefault) {
7768 return r1.isDefault ? -1 : 1;
7772 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
7774 return (v1 > v2) ? -1 : 1;
7776 if (r1.system != r2.system) {
7777 return r1.system ? -1 : 1;
7783 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
7784 new Comparator<ProviderInfo>() {
7785 public int compare(ProviderInfo p1, ProviderInfo p2) {
7786 final int v1 = p1.initOrder;
7787 final int v2 = p2.initOrder;
7788 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
7792 static final void sendPackageBroadcast(String action, String pkg,
7793 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
7795 IActivityManager am = ActivityManagerNative.getDefault();
7798 if (userIds == null) {
7799 userIds = am.getRunningUserIds();
7801 for (int id : userIds) {
7802 final Intent intent = new Intent(action,
7803 pkg != null ? Uri.fromParts("package", pkg, null) : null);
7804 if (extras != null) {
7805 intent.putExtras(extras);
7807 if (targetPkg != null) {
7808 intent.setPackage(targetPkg);
7810 // Modify the UID when posting to other users
7811 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
7812 if (uid > 0 && UserHandle.getUserId(uid) != id) {
7813 uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
7814 intent.putExtra(Intent.EXTRA_UID, uid);
7816 intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
7817 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
7818 if (DEBUG_BROADCASTS) {
7819 RuntimeException here = new RuntimeException("here");
7820 here.fillInStackTrace();
7821 Slog.d(TAG, "Sending to user " + id + ": "
7822 + intent.toShortString(false, true, false, false)
7823 + " " + intent.getExtras(), here);
7825 am.broadcastIntent(null, intent, null, finishedReceiver,
7826 0, null, null, null, android.app.AppOpsManager.OP_NONE,
7827 finishedReceiver != null, false, id);
7829 } catch (RemoteException ex) {
7835 * Check if the external storage media is available. This is true if there
7836 * is a mounted external storage medium or if the external storage is
7839 private boolean isExternalMediaAvailable() {
7840 return mMediaMounted || Environment.isExternalStorageEmulated();
7844 public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
7846 synchronized (mPackages) {
7847 if (!isExternalMediaAvailable()) {
7848 // If the external storage is no longer mounted at this point,
7849 // the caller may not have been able to delete all of this
7850 // packages files and can not delete any more. Bail.
7853 final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
7854 if (lastPackage != null) {
7855 pkgs.remove(lastPackage);
7857 if (pkgs.size() > 0) {
7864 void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
7865 final Message msg = mHandler.obtainMessage(START_CLEANING_PACKAGE,
7866 userId, andCode ? 1 : 0, packageName);
7870 if (mPostSystemReadyMessages == null) {
7871 mPostSystemReadyMessages = new ArrayList<>();
7873 mPostSystemReadyMessages.add(msg);
7877 void startCleaningPackages() {
7879 synchronized (mPackages) {
7880 if (!isExternalMediaAvailable()) {
7883 if (mSettings.mPackagesToBeCleaned.isEmpty()) {
7887 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
7888 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
7889 IActivityManager am = ActivityManagerNative.getDefault();
7892 am.startService(null, intent, null, UserHandle.USER_OWNER);
7893 } catch (RemoteException e) {
7899 public void installPackage(String originPath, IPackageInstallObserver2 observer,
7900 int installFlags, String installerPackageName, VerificationParams verificationParams,
7901 String packageAbiOverride) {
7902 installPackageAsUser(originPath, observer, installFlags, installerPackageName, verificationParams,
7903 packageAbiOverride, UserHandle.getCallingUserId());
7907 public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
7908 int installFlags, String installerPackageName, VerificationParams verificationParams,
7909 String packageAbiOverride, int userId) {
7910 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
7912 final int callingUid = Binder.getCallingUid();
7913 enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
7915 if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
7917 if (observer != null) {
7918 observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
7920 } catch (RemoteException re) {
7925 if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
7926 installFlags |= PackageManager.INSTALL_FROM_ADB;
7929 // Caller holds INSTALL_PACKAGES permission, so we're less strict
7930 // about installerPackageName.
7932 installFlags &= ~PackageManager.INSTALL_FROM_ADB;
7933 installFlags &= ~PackageManager.INSTALL_ALL_USERS;
7937 if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
7938 user = UserHandle.ALL;
7940 user = new UserHandle(userId);
7943 verificationParams.setInstallerUid(callingUid);
7945 final File originFile = new File(originPath);
7946 final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
7948 final Message msg = mHandler.obtainMessage(INIT_COPY);
7949 msg.obj = new InstallParams(origin, observer, installFlags,
7950 installerPackageName, verificationParams, user, packageAbiOverride);
7951 mHandler.sendMessage(msg);
7954 void installStage(String packageName, File stagedDir, String stagedCid,
7955 IPackageInstallObserver2 observer, PackageInstaller.SessionParams params,
7956 String installerPackageName, int installerUid, UserHandle user) {
7957 final VerificationParams verifParams = new VerificationParams(null, params.originatingUri,
7958 params.referrerUri, installerUid, null);
7960 final OriginInfo origin;
7961 if (stagedDir != null) {
7962 origin = OriginInfo.fromStagedFile(stagedDir);
7964 origin = OriginInfo.fromStagedContainer(stagedCid);
7967 final Message msg = mHandler.obtainMessage(INIT_COPY);
7968 msg.obj = new InstallParams(origin, observer, params.installFlags,
7969 installerPackageName, verifParams, user, params.abiOverride);
7970 mHandler.sendMessage(msg);
7973 private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting, int userId) {
7974 Bundle extras = new Bundle(1);
7975 extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
7977 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
7978 packageName, extras, null, null, new int[] {userId});
7980 IActivityManager am = ActivityManagerNative.getDefault();
7981 final boolean isSystem =
7982 isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
7983 if (isSystem && am.isUserRunning(userId, false)) {
7984 // The just-installed/enabled app is bundled on the system, so presumed
7985 // to be able to run automatically without needing an explicit launch.
7986 // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
7987 Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
7988 .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
7989 .setPackage(packageName);
7990 am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
7991 android.app.AppOpsManager.OP_NONE, false, false, userId);
7993 } catch (RemoteException e) {
7995 Slog.w(TAG, "Unable to bootstrap installed package", e);
8000 public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
8002 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
8003 PackageSetting pkgSetting;
8004 final int uid = Binder.getCallingUid();
8005 enforceCrossUserPermission(uid, userId, true, true,
8006 "setApplicationHiddenSetting for user " + userId);
8008 if (hidden && isPackageDeviceAdmin(packageName, userId)) {
8009 Slog.w(TAG, "Not hiding package " + packageName + ": has active device admin");
8013 long callingId = Binder.clearCallingIdentity();
8015 boolean sendAdded = false;
8016 boolean sendRemoved = false;
8018 synchronized (mPackages) {
8019 pkgSetting = mSettings.mPackages.get(packageName);
8020 if (pkgSetting == null) {
8023 if (pkgSetting.getHidden(userId) != hidden) {
8024 pkgSetting.setHidden(hidden, userId);
8025 mSettings.writePackageRestrictionsLPr(userId);
8034 sendPackageAddedForUser(packageName, pkgSetting, userId);
8038 killApplication(packageName, UserHandle.getUid(userId, pkgSetting.appId),
8040 sendApplicationHiddenForUser(packageName, pkgSetting, userId);
8043 Binder.restoreCallingIdentity(callingId);
8048 private void sendApplicationHiddenForUser(String packageName, PackageSetting pkgSetting,
8050 final PackageRemovedInfo info = new PackageRemovedInfo();
8051 info.removedPackage = packageName;
8052 info.removedUsers = new int[] {userId};
8053 info.uid = UserHandle.getUid(userId, pkgSetting.appId);
8054 info.sendBroadcast(false, false, false);
8058 * Returns true if application is not found or there was an error. Otherwise it returns
8059 * the hidden state of the package for the given user.
8062 public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
8063 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
8064 enforceCrossUserPermission(Binder.getCallingUid(), userId, true,
8065 false, "getApplicationHidden for user " + userId);
8066 PackageSetting pkgSetting;
8067 long callingId = Binder.clearCallingIdentity();
8070 synchronized (mPackages) {
8071 pkgSetting = mSettings.mPackages.get(packageName);
8072 if (pkgSetting == null) {
8075 return pkgSetting.getHidden(userId);
8078 Binder.restoreCallingIdentity(callingId);
8086 public int installExistingPackageAsUser(String packageName, int userId) {
8087 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
8089 PackageSetting pkgSetting;
8090 final int uid = Binder.getCallingUid();
8091 enforceCrossUserPermission(uid, userId, true, true, "installExistingPackage for user "
8093 if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
8094 return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
8097 long callingId = Binder.clearCallingIdentity();
8099 boolean sendAdded = false;
8100 Bundle extras = new Bundle(1);
8103 synchronized (mPackages) {
8104 pkgSetting = mSettings.mPackages.get(packageName);
8105 if (pkgSetting == null) {
8106 return PackageManager.INSTALL_FAILED_INVALID_URI;
8108 if (!pkgSetting.getInstalled(userId)) {
8109 pkgSetting.setInstalled(true, userId);
8110 pkgSetting.setHidden(false, userId);
8111 mSettings.writePackageRestrictionsLPr(userId);
8117 sendPackageAddedForUser(packageName, pkgSetting, userId);
8120 Binder.restoreCallingIdentity(callingId);
8123 return PackageManager.INSTALL_SUCCEEDED;
8126 boolean isUserRestricted(int userId, String restrictionKey) {
8127 Bundle restrictions = sUserManager.getUserRestrictions(userId);
8128 if (restrictions.getBoolean(restrictionKey, false)) {
8129 Log.w(TAG, "User is restricted: " + restrictionKey);
8136 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
8137 mContext.enforceCallingOrSelfPermission(
8138 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
8139 "Only package verification agents can verify applications");
8141 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
8142 final PackageVerificationResponse response = new PackageVerificationResponse(
8143 verificationCode, Binder.getCallingUid());
8146 mHandler.sendMessage(msg);
8150 public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
8151 long millisecondsToDelay) {
8152 mContext.enforceCallingOrSelfPermission(
8153 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
8154 "Only package verification agents can extend verification timeouts");
8156 final PackageVerificationState state = mPendingVerification.get(id);
8157 final PackageVerificationResponse response = new PackageVerificationResponse(
8158 verificationCodeAtTimeout, Binder.getCallingUid());
8160 if (millisecondsToDelay > PackageManager.MAXIMUM_VERIFICATION_TIMEOUT) {
8161 millisecondsToDelay = PackageManager.MAXIMUM_VERIFICATION_TIMEOUT;
8163 if (millisecondsToDelay < 0) {
8164 millisecondsToDelay = 0;
8166 if ((verificationCodeAtTimeout != PackageManager.VERIFICATION_ALLOW)
8167 && (verificationCodeAtTimeout != PackageManager.VERIFICATION_REJECT)) {
8168 verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
8171 if ((state != null) && !state.timeoutExtended()) {
8172 state.extendTimeout();
8174 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
8177 mHandler.sendMessageDelayed(msg, millisecondsToDelay);
8181 private void broadcastPackageVerified(int verificationId, Uri packageUri,
8182 int verificationCode, UserHandle user) {
8183 final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
8184 intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
8185 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
8186 intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
8187 intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode);
8189 mContext.sendBroadcastAsUser(intent, user,
8190 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
8193 private ComponentName matchComponentForVerifier(String packageName,
8194 List<ResolveInfo> receivers) {
8195 ActivityInfo targetReceiver = null;
8197 final int NR = receivers.size();
8198 for (int i = 0; i < NR; i++) {
8199 final ResolveInfo info = receivers.get(i);
8200 if (info.activityInfo == null) {
8204 if (packageName.equals(info.activityInfo.packageName)) {
8205 targetReceiver = info.activityInfo;
8210 if (targetReceiver == null) {
8214 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
8217 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
8218 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
8219 if (pkgInfo.verifiers.length == 0) {
8223 final int N = pkgInfo.verifiers.length;
8224 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
8225 for (int i = 0; i < N; i++) {
8226 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
8228 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
8234 final int verifierUid = getUidForVerifier(verifierInfo);
8235 if (verifierUid == -1) {
8240 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
8241 + " with the correct signature");
8243 sufficientVerifiers.add(comp);
8244 verificationState.addSufficientVerifier(verifierUid);
8247 return sufficientVerifiers;
8250 private int getUidForVerifier(VerifierInfo verifierInfo) {
8251 synchronized (mPackages) {
8252 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
8255 } else if (pkg.mSignatures.length != 1) {
8256 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
8257 + " has more than one signature; ignoring");
8262 * If the public key of the package's signature does not match
8263 * our expected public key, then this is a different package and
8267 final byte[] expectedPublicKey;
8269 final Signature verifierSig = pkg.mSignatures[0];
8270 final PublicKey publicKey = verifierSig.getPublicKey();
8271 expectedPublicKey = publicKey.getEncoded();
8272 } catch (CertificateException e) {
8276 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
8278 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
8279 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
8280 + " does not have the expected public key; ignoring");
8284 return pkg.applicationInfo.uid;
8289 public void finishPackageInstall(int token) {
8290 enforceSystemOrRoot("Only the system is allowed to finish installs");
8292 if (DEBUG_INSTALL) {
8293 Slog.v(TAG, "BM finishing package install for " + token);
8296 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
8297 mHandler.sendMessage(msg);
8301 * Get the verification agent timeout.
8303 * @return verification timeout in milliseconds
8305 private long getVerificationTimeout() {
8306 return android.provider.Settings.Global.getLong(mContext.getContentResolver(),
8307 android.provider.Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
8308 DEFAULT_VERIFICATION_TIMEOUT);
8312 * Get the default verification agent response code.
8314 * @return default verification response code
8316 private int getDefaultVerificationResponse() {
8317 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
8318 android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
8319 DEFAULT_VERIFICATION_RESPONSE);
8323 * Check whether or not package verification has been enabled.
8325 * @return true if verification should be performed
8327 private boolean isVerificationEnabled(int userId, int installFlags) {
8328 if (!DEFAULT_VERIFY_ENABLE) {
8332 boolean ensureVerifyAppsEnabled = isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS);
8334 // Check if installing from ADB
8335 if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
8336 // Do not run verification in a test harness environment
8337 if (ActivityManager.isRunningInTestHarness()) {
8340 if (ensureVerifyAppsEnabled) {
8343 // Check if the developer does not want package verification for ADB installs
8344 if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
8345 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
8350 if (ensureVerifyAppsEnabled) {
8354 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
8355 android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
8359 * Get the "allow unknown sources" setting.
8361 * @return the current "allow unknown sources" setting
8363 private int getUnknownSourcesSettings() {
8364 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
8365 android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
8370 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
8371 final int uid = Binder.getCallingUid();
8373 synchronized (mPackages) {
8374 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
8375 if (targetPackageSetting == null) {
8376 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
8379 PackageSetting installerPackageSetting;
8380 if (installerPackageName != null) {
8381 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
8382 if (installerPackageSetting == null) {
8383 throw new IllegalArgumentException("Unknown installer package: "
8384 + installerPackageName);
8387 installerPackageSetting = null;
8390 Signature[] callerSignature;
8391 Object obj = mSettings.getUserIdLPr(uid);
8393 if (obj instanceof SharedUserSetting) {
8394 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
8395 } else if (obj instanceof PackageSetting) {
8396 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
8398 throw new SecurityException("Bad object " + obj + " for uid " + uid);
8401 throw new SecurityException("Unknown calling uid " + uid);
8404 // Verify: can't set installerPackageName to a package that is
8405 // not signed with the same cert as the caller.
8406 if (installerPackageSetting != null) {
8407 if (compareSignatures(callerSignature,
8408 installerPackageSetting.signatures.mSignatures)
8409 != PackageManager.SIGNATURE_MATCH) {
8410 throw new SecurityException(
8411 "Caller does not have same cert as new installer package "
8412 + installerPackageName);
8416 // Verify: if target already has an installer package, it must
8417 // be signed with the same cert as the caller.
8418 if (targetPackageSetting.installerPackageName != null) {
8419 PackageSetting setting = mSettings.mPackages.get(
8420 targetPackageSetting.installerPackageName);
8421 // If the currently set package isn't valid, then it's always
8422 // okay to change it.
8423 if (setting != null) {
8424 if (compareSignatures(callerSignature,
8425 setting.signatures.mSignatures)
8426 != PackageManager.SIGNATURE_MATCH) {
8427 throw new SecurityException(
8428 "Caller does not have same cert as old installer package "
8429 + targetPackageSetting.installerPackageName);
8435 targetPackageSetting.installerPackageName = installerPackageName;
8436 scheduleWriteSettingsLocked();
8440 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
8441 // Queue up an async operation since the package installation may take a little while.
8442 mHandler.post(new Runnable() {
8444 mHandler.removeCallbacks(this);
8445 // Result object to be returned
8446 PackageInstalledInfo res = new PackageInstalledInfo();
8447 res.returnCode = currentStatus;
8450 res.removedInfo = new PackageRemovedInfo();
8451 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
8452 args.doPreInstall(res.returnCode);
8453 synchronized (mInstallLock) {
8454 installPackageLI(args, res);
8456 args.doPostInstall(res.returnCode, res.uid);
8459 // A restore should be performed at this point if (a) the install
8460 // succeeded, (b) the operation is not an update, and (c) the new
8461 // package has not opted out of backup participation.
8462 final boolean update = res.removedInfo.removedPackage != null;
8463 final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
8464 boolean doRestore = !update
8465 && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
8467 // Set up the post-install work request bookkeeping. This will be used
8468 // and cleaned up by the post-install event handling regardless of whether
8469 // there's a restore pass performed. Token values are >= 1.
8471 if (mNextInstallToken < 0) mNextInstallToken = 1;
8472 token = mNextInstallToken++;
8474 PostInstallData data = new PostInstallData(args, res);
8475 mRunningInstalls.put(token, data);
8476 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
8478 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
8479 // Pass responsibility to the Backup Manager. It will perform a
8480 // restore if appropriate, then pass responsibility back to the
8481 // Package Manager to run the post-install observer callbacks
8483 IBackupManager bm = IBackupManager.Stub.asInterface(
8484 ServiceManager.getService(Context.BACKUP_SERVICE));
8486 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
8487 + " to BM for possible restore");
8489 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
8490 } catch (RemoteException e) {
8491 // can't happen; the backup manager is local
8492 } catch (Exception e) {
8493 Slog.e(TAG, "Exception trying to enqueue restore", e);
8497 Slog.e(TAG, "Backup Manager not found!");
8503 // No restore possible, or the Backup Manager was mysteriously not
8504 // available -- just fire the post-install work request directly.
8505 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
8506 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
8507 mHandler.sendMessage(msg);
8513 private abstract class HandlerParams {
8514 private static final int MAX_RETRIES = 4;
8517 * Number of times startCopy() has been attempted and had a non-fatal
8520 private int mRetries = 0;
8522 /** User handle for the user requesting the information or installation. */
8523 private final UserHandle mUser;
8525 HandlerParams(UserHandle user) {
8529 UserHandle getUser() {
8533 final boolean startCopy() {
8536 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
8538 if (++mRetries > MAX_RETRIES) {
8539 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
8540 mHandler.sendEmptyMessage(MCS_GIVE_UP);
8541 handleServiceError();
8547 } catch (RemoteException e) {
8548 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
8549 mHandler.sendEmptyMessage(MCS_RECONNECT);
8556 final void serviceError() {
8557 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
8558 handleServiceError();
8562 abstract void handleStartCopy() throws RemoteException;
8563 abstract void handleServiceError();
8564 abstract void handleReturnCode();
8567 class MeasureParams extends HandlerParams {
8568 private final PackageStats mStats;
8569 private boolean mSuccess;
8571 private final IPackageStatsObserver mObserver;
8573 public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
8574 super(new UserHandle(stats.userHandle));
8575 mObserver = observer;
8580 public String toString() {
8581 return "MeasureParams{"
8582 + Integer.toHexString(System.identityHashCode(this))
8583 + " " + mStats.packageName + "}";
8587 void handleStartCopy() throws RemoteException {
8588 synchronized (mInstallLock) {
8589 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
8593 final boolean mounted;
8594 if (Environment.isExternalStorageEmulated()) {
8597 final String status = Environment.getExternalStorageState();
8598 mounted = (Environment.MEDIA_MOUNTED.equals(status)
8599 || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
8603 final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
8605 mStats.externalCacheSize = calculateDirectorySize(mContainerService,
8606 userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
8608 mStats.externalDataSize = calculateDirectorySize(mContainerService,
8609 userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
8611 // Always subtract cache size, since it's a subdirectory
8612 mStats.externalDataSize -= mStats.externalCacheSize;
8614 mStats.externalMediaSize = calculateDirectorySize(mContainerService,
8615 userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
8617 mStats.externalObbSize = calculateDirectorySize(mContainerService,
8618 userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
8624 void handleReturnCode() {
8625 if (mObserver != null) {
8627 mObserver.onGetStatsCompleted(mStats, mSuccess);
8628 } catch (RemoteException e) {
8629 Slog.i(TAG, "Observer no longer exists.");
8635 void handleServiceError() {
8636 Slog.e(TAG, "Could not measure application " + mStats.packageName
8637 + " external storage");
8641 private static long calculateDirectorySize(IMediaContainerService mcs, File[] paths)
8642 throws RemoteException {
8644 for (File path : paths) {
8645 result += mcs.calculateDirectorySize(path.getAbsolutePath());
8650 private static void clearDirectory(IMediaContainerService mcs, File[] paths) {
8651 for (File path : paths) {
8653 mcs.clearDirectory(path.getAbsolutePath());
8654 } catch (RemoteException e) {
8659 static class OriginInfo {
8661 * Location where install is coming from, before it has been
8662 * copied/renamed into place. This could be a single monolithic APK
8663 * file, or a cluster directory. This location may be untrusted.
8669 * Flag indicating that {@link #file} or {@link #cid} has already been
8670 * staged, meaning downstream users don't need to defensively copy the
8673 final boolean staged;
8676 * Flag indicating that {@link #file} or {@link #cid} is an already
8677 * installed app that is being moved.
8679 final boolean existing;
8681 final String resolvedPath;
8682 final File resolvedFile;
8684 static OriginInfo fromNothing() {
8685 return new OriginInfo(null, null, false, false);
8688 static OriginInfo fromUntrustedFile(File file) {
8689 return new OriginInfo(file, null, false, false);
8692 static OriginInfo fromExistingFile(File file) {
8693 return new OriginInfo(file, null, false, true);
8696 static OriginInfo fromStagedFile(File file) {
8697 return new OriginInfo(file, null, true, false);
8700 static OriginInfo fromStagedContainer(String cid) {
8701 return new OriginInfo(null, cid, true, false);
8704 private OriginInfo(File file, String cid, boolean staged, boolean existing) {
8707 this.staged = staged;
8708 this.existing = existing;
8711 resolvedPath = PackageHelper.getSdDir(cid);
8712 resolvedFile = new File(resolvedPath);
8713 } else if (file != null) {
8714 resolvedPath = file.getAbsolutePath();
8715 resolvedFile = file;
8717 resolvedPath = null;
8718 resolvedFile = null;
8723 class InstallParams extends HandlerParams {
8724 final OriginInfo origin;
8725 final IPackageInstallObserver2 observer;
8727 final String installerPackageName;
8728 final VerificationParams verificationParams;
8729 private InstallArgs mArgs;
8731 final String packageAbiOverride;
8733 InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
8734 String installerPackageName, VerificationParams verificationParams, UserHandle user,
8735 String packageAbiOverride) {
8737 this.origin = origin;
8738 this.observer = observer;
8739 this.installFlags = installFlags;
8740 this.installerPackageName = installerPackageName;
8741 this.verificationParams = verificationParams;
8742 this.packageAbiOverride = packageAbiOverride;
8746 public String toString() {
8747 return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
8748 + " file=" + origin.file + " cid=" + origin.cid + "}";
8751 public ManifestDigest getManifestDigest() {
8752 if (verificationParams == null) {
8755 return verificationParams.getManifestDigest();
8758 private int installLocationPolicy(PackageInfoLite pkgLite) {
8759 String packageName = pkgLite.packageName;
8760 int installLocation = pkgLite.installLocation;
8761 boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
8763 synchronized (mPackages) {
8764 PackageParser.Package pkg = mPackages.get(packageName);
8766 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
8767 // Check for downgrading.
8768 if ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
8769 if (pkgLite.versionCode < pkg.mVersionCode) {
8770 Slog.w(TAG, "Can't install update of " + packageName
8771 + " update version " + pkgLite.versionCode
8772 + " is older than installed version "
8773 + pkg.mVersionCode);
8774 return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
8777 // Check for updated system application.
8778 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
8780 Slog.w(TAG, "Cannot install update to system app on sdcard");
8781 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
8783 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
8786 // Install flag overrides everything.
8787 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
8789 // If current upgrade specifies particular preference
8790 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
8791 // Application explicitly specified internal.
8792 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
8793 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
8794 // App explictly prefers external. Let policy decide
8796 // Prefer previous location
8797 if (isExternal(pkg)) {
8798 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
8800 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
8804 // Invalid install. Return error code
8805 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
8809 // All the special cases have been taken care of.
8810 // Return result based on recommended install location.
8812 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
8814 return pkgLite.recommendedInstallLocation;
8818 * Invoke remote method to get package information and install
8819 * location values. Override install location based on default
8820 * policy if needed and then create install arguments based
8821 * on the install location.
8823 public void handleStartCopy() throws RemoteException {
8824 int ret = PackageManager.INSTALL_SUCCEEDED;
8826 // If we're already staged, we've firmly committed to an install location
8827 if (origin.staged) {
8828 if (origin.file != null) {
8829 installFlags |= PackageManager.INSTALL_INTERNAL;
8830 installFlags &= ~PackageManager.INSTALL_EXTERNAL;
8831 } else if (origin.cid != null) {
8832 installFlags |= PackageManager.INSTALL_EXTERNAL;
8833 installFlags &= ~PackageManager.INSTALL_INTERNAL;
8835 throw new IllegalStateException("Invalid stage location");
8839 final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
8840 final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
8842 PackageInfoLite pkgLite = null;
8844 if (onInt && onSd) {
8845 // Check if both bits are set.
8846 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
8847 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
8849 pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
8850 packageAbiOverride);
8853 * If we have too little free space, try to free cache
8856 if (!origin.staged && pkgLite.recommendedInstallLocation
8857 == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
8858 // TODO: focus freeing disk space on the target device
8859 final StorageManager storage = StorageManager.from(mContext);
8860 final long lowThreshold = storage.getStorageLowBytes(
8861 Environment.getDataDirectory());
8863 final long sizeBytes = mContainerService.calculateInstalledSize(
8864 origin.resolvedPath, isForwardLocked(), packageAbiOverride);
8866 if (mInstaller.freeCache(sizeBytes + lowThreshold) >= 0) {
8867 pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
8868 installFlags, packageAbiOverride);
8872 * The cache free must have deleted the file we
8873 * downloaded to install.
8875 * TODO: fix the "freeCache" call to not delete
8876 * the file we care about.
8878 if (pkgLite.recommendedInstallLocation
8879 == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
8880 pkgLite.recommendedInstallLocation
8881 = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
8886 if (ret == PackageManager.INSTALL_SUCCEEDED) {
8887 int loc = pkgLite.recommendedInstallLocation;
8888 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
8889 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
8890 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
8891 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
8892 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
8893 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8894 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
8895 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
8896 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
8897 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
8898 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
8899 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
8901 // Override with defaults if needed.
8902 loc = installLocationPolicy(pkgLite);
8903 if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
8904 ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
8905 } else if (!onSd && !onInt) {
8906 // Override install location with flags
8907 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
8908 // Set the flag to install on external media.
8909 installFlags |= PackageManager.INSTALL_EXTERNAL;
8910 installFlags &= ~PackageManager.INSTALL_INTERNAL;
8912 // Make sure the flag for installing on external
8914 installFlags |= PackageManager.INSTALL_INTERNAL;
8915 installFlags &= ~PackageManager.INSTALL_EXTERNAL;
8921 final InstallArgs args = createInstallArgs(this);
8924 if (ret == PackageManager.INSTALL_SUCCEEDED) {
8926 * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
8927 * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
8929 int userIdentifier = getUser().getIdentifier();
8930 if (userIdentifier == UserHandle.USER_ALL
8931 && ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) {
8932 userIdentifier = UserHandle.USER_OWNER;
8936 * Determine if we have any installed package verifiers. If we
8937 * do, then we'll defer to them to verify the packages.
8939 final int requiredUid = mRequiredVerifierPackage == null ? -1
8940 : getPackageUid(mRequiredVerifierPackage, userIdentifier);
8941 if (!origin.existing && requiredUid != -1
8942 && isVerificationEnabled(userIdentifier, installFlags)) {
8943 final Intent verification = new Intent(
8944 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
8945 verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
8947 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
8949 final List<ResolveInfo> receivers = queryIntentReceivers(verification,
8950 PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
8951 0 /* TODO: Which userId? */);
8954 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
8955 + verification.toString() + " with " + pkgLite.verifiers.length
8956 + " optional verifiers");
8959 final int verificationId = mPendingVerificationToken++;
8961 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
8963 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
8964 installerPackageName);
8966 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
8969 verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
8970 pkgLite.packageName);
8972 verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
8973 pkgLite.versionCode);
8975 if (verificationParams != null) {
8976 if (verificationParams.getVerificationURI() != null) {
8977 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
8978 verificationParams.getVerificationURI());
8980 if (verificationParams.getOriginatingURI() != null) {
8981 verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
8982 verificationParams.getOriginatingURI());
8984 if (verificationParams.getReferrer() != null) {
8985 verification.putExtra(Intent.EXTRA_REFERRER,
8986 verificationParams.getReferrer());
8988 if (verificationParams.getOriginatingUid() >= 0) {
8989 verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
8990 verificationParams.getOriginatingUid());
8992 if (verificationParams.getInstallerUid() >= 0) {
8993 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
8994 verificationParams.getInstallerUid());
8998 final PackageVerificationState verificationState = new PackageVerificationState(
9001 mPendingVerification.append(verificationId, verificationState);
9003 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
9004 receivers, verificationState);
9007 * If any sufficient verifiers were listed in the package
9008 * manifest, attempt to ask them.
9010 if (sufficientVerifiers != null) {
9011 final int N = sufficientVerifiers.size();
9013 Slog.i(TAG, "Additional verifiers required, but none installed.");
9014 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
9016 for (int i = 0; i < N; i++) {
9017 final ComponentName verifierComponent = sufficientVerifiers.get(i);
9019 final Intent sufficientIntent = new Intent(verification);
9020 sufficientIntent.setComponent(verifierComponent);
9022 mContext.sendBroadcastAsUser(sufficientIntent, getUser());
9027 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
9028 mRequiredVerifierPackage, receivers);
9029 if (ret == PackageManager.INSTALL_SUCCEEDED
9030 && mRequiredVerifierPackage != null) {
9032 * Send the intent to the required verification agent,
9033 * but only start the verification timeout after the
9034 * target BroadcastReceivers have run.
9036 verification.setComponent(requiredVerifierComponent);
9037 mContext.sendOrderedBroadcastAsUser(verification, getUser(),
9038 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
9039 new BroadcastReceiver() {
9041 public void onReceive(Context context, Intent intent) {
9042 final Message msg = mHandler
9043 .obtainMessage(CHECK_PENDING_VERIFICATION);
9044 msg.arg1 = verificationId;
9045 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
9047 }, null, 0, null, null);
9050 * We don't want the copy to proceed until verification
9051 * succeeds, so null out this field.
9057 * No package verification is enabled, so immediately start
9058 * the remote call to initiate copy using temporary file.
9060 ret = args.copyApk(mContainerService, true);
9068 void handleReturnCode() {
9069 // If mArgs is null, then MCS couldn't be reached. When it
9070 // reconnects, it will try again to install. At that point, this
9072 if (mArgs != null) {
9073 processPendingInstall(mArgs, mRet);
9078 void handleServiceError() {
9079 mArgs = createInstallArgs(this);
9080 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
9083 public boolean isForwardLocked() {
9084 return (installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
9089 * Used during creation of InstallArgs
9091 * @param installFlags package installation flags
9092 * @return true if should be installed on external storage
9094 private static boolean installOnSd(int installFlags) {
9095 if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
9098 if ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
9105 * Used during creation of InstallArgs
9107 * @param installFlags package installation flags
9108 * @return true if should be installed as forward locked
9110 private static boolean installForwardLocked(int installFlags) {
9111 return (installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
9114 private InstallArgs createInstallArgs(InstallParams params) {
9115 if (installOnSd(params.installFlags) || params.isForwardLocked()) {
9116 return new AsecInstallArgs(params);
9118 return new FileInstallArgs(params);
9123 * Create args that describe an existing installed package. Typically used
9124 * when cleaning up old installs, or used as a move source.
9126 private InstallArgs createInstallArgsForExisting(int installFlags, String codePath,
9127 String resourcePath, String nativeLibraryRoot, String[] instructionSets) {
9128 final boolean isInAsec;
9129 if (installOnSd(installFlags)) {
9130 /* Apps on SD card are always in ASEC containers. */
9132 } else if (installForwardLocked(installFlags)
9133 && !codePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
9135 * Forward-locked apps are only in ASEC containers if they're the
9144 return new AsecInstallArgs(codePath, instructionSets,
9145 installOnSd(installFlags), installForwardLocked(installFlags));
9147 return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
9152 static abstract class InstallArgs {
9153 /** @see InstallParams#origin */
9154 final OriginInfo origin;
9156 final IPackageInstallObserver2 observer;
9157 // Always refers to PackageManager flags only
9158 final int installFlags;
9159 final String installerPackageName;
9160 final ManifestDigest manifestDigest;
9161 final UserHandle user;
9162 final String abiOverride;
9164 // The list of instruction sets supported by this app. This is currently
9165 // only used during the rmdex() phase to clean up resources. We can get rid of this
9166 // if we move dex files under the common app path.
9167 /* nullable */ String[] instructionSets;
9169 InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
9170 String installerPackageName, ManifestDigest manifestDigest, UserHandle user,
9171 String[] instructionSets, String abiOverride) {
9172 this.origin = origin;
9173 this.installFlags = installFlags;
9174 this.observer = observer;
9175 this.installerPackageName = installerPackageName;
9176 this.manifestDigest = manifestDigest;
9178 this.instructionSets = instructionSets;
9179 this.abiOverride = abiOverride;
9182 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
9183 abstract int doPreInstall(int status);
9186 * Rename package into final resting place. All paths on the given
9187 * scanned package should be updated to reflect the rename.
9189 abstract boolean doRename(int status, PackageParser.Package pkg, String oldCodePath);
9190 abstract int doPostInstall(int status, int uid);
9192 /** @see PackageSettingBase#codePathString */
9193 abstract String getCodePath();
9194 /** @see PackageSettingBase#resourcePathString */
9195 abstract String getResourcePath();
9196 abstract String getLegacyNativeLibraryPath();
9198 // Need installer lock especially for dex file removal.
9199 abstract void cleanUpResourcesLI();
9200 abstract boolean doPostDeleteLI(boolean delete);
9201 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
9204 * Called before the source arguments are copied. This is used mostly
9205 * for MoveParams when it needs to read the source file to put it in the
9209 return PackageManager.INSTALL_SUCCEEDED;
9213 * Called after the source arguments are copied. This is used mostly for
9214 * MoveParams when it needs to read the source file to put it in the
9219 int doPostCopy(int uid) {
9220 return PackageManager.INSTALL_SUCCEEDED;
9223 protected boolean isFwdLocked() {
9224 return (installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
9227 protected boolean isExternal() {
9228 return (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
9231 UserHandle getUser() {
9237 * Logic to handle installation of non-ASEC applications, including copying
9238 * and renaming logic.
9240 class FileInstallArgs extends InstallArgs {
9241 private File codeFile;
9242 private File resourceFile;
9243 private File legacyNativeLibraryPath;
9245 // Example topology:
9246 // /data/app/com.example/base.apk
9247 // /data/app/com.example/split_foo.apk
9248 // /data/app/com.example/lib/arm/libfoo.so
9249 // /data/app/com.example/lib/arm64/libfoo.so
9250 // /data/app/com.example/dalvik/arm/base.apk@classes.dex
9253 FileInstallArgs(InstallParams params) {
9254 super(params.origin, params.observer, params.installFlags,
9255 params.installerPackageName, params.getManifestDigest(), params.getUser(),
9256 null /* instruction sets */, params.packageAbiOverride);
9257 if (isFwdLocked()) {
9258 throw new IllegalArgumentException("Forward locking only supported in ASEC");
9262 /** Existing install */
9263 FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath,
9264 String[] instructionSets) {
9265 super(OriginInfo.fromNothing(), null, 0, null, null, null, instructionSets, null);
9266 this.codeFile = (codePath != null) ? new File(codePath) : null;
9267 this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
9268 this.legacyNativeLibraryPath = (legacyNativeLibraryPath != null) ?
9269 new File(legacyNativeLibraryPath) : null;
9272 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
9273 final long sizeBytes = imcs.calculateInstalledSize(origin.file.getAbsolutePath(),
9274 isFwdLocked(), abiOverride);
9276 final StorageManager storage = StorageManager.from(mContext);
9277 return (sizeBytes <= storage.getStorageBytesUntilLow(Environment.getDataDirectory()));
9280 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
9281 if (origin.staged) {
9282 Slog.d(TAG, origin.file + " already staged; skipping copy");
9283 codeFile = origin.file;
9284 resourceFile = origin.file;
9285 return PackageManager.INSTALL_SUCCEEDED;
9289 final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
9291 resourceFile = tempDir;
9292 } catch (IOException e) {
9293 Slog.w(TAG, "Failed to create copy file: " + e);
9294 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
9297 final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
9299 public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
9300 if (!FileUtils.isValidExtFilename(name)) {
9301 throw new IllegalArgumentException("Invalid filename: " + name);
9304 final File file = new File(codeFile, name);
9305 final FileDescriptor fd = Os.open(file.getAbsolutePath(),
9306 O_RDWR | O_CREAT, 0644);
9307 Os.chmod(file.getAbsolutePath(), 0644);
9308 return new ParcelFileDescriptor(fd);
9309 } catch (ErrnoException e) {
9310 throw new RemoteException("Failed to open: " + e.getMessage());
9315 int ret = PackageManager.INSTALL_SUCCEEDED;
9316 ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
9317 if (ret != PackageManager.INSTALL_SUCCEEDED) {
9318 Slog.e(TAG, "Failed to copy package");
9322 final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
9323 NativeLibraryHelper.Handle handle = null;
9325 handle = NativeLibraryHelper.Handle.create(codeFile);
9326 ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
9328 } catch (IOException e) {
9329 Slog.e(TAG, "Copying native libraries failed", e);
9330 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
9332 IoUtils.closeQuietly(handle);
9338 int doPreInstall(int status) {
9339 if (status != PackageManager.INSTALL_SUCCEEDED) {
9345 boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
9346 if (status != PackageManager.INSTALL_SUCCEEDED) {
9350 final File beforeCodeFile = codeFile;
9351 final File afterCodeFile = getNextCodePath(pkg.packageName);
9353 Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
9355 Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
9356 } catch (ErrnoException e) {
9357 Slog.d(TAG, "Failed to rename", e);
9361 if (!SELinux.restoreconRecursive(afterCodeFile)) {
9362 Slog.d(TAG, "Failed to restorecon");
9366 // Reflect the rename internally
9367 codeFile = afterCodeFile;
9368 resourceFile = afterCodeFile;
9370 // Reflect the rename in scanned details
9371 pkg.codePath = afterCodeFile.getAbsolutePath();
9372 pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
9374 pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
9375 pkg.splitCodePaths);
9377 // Reflect the rename in app info
9378 pkg.applicationInfo.setCodePath(pkg.codePath);
9379 pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
9380 pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
9381 pkg.applicationInfo.setResourcePath(pkg.codePath);
9382 pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
9383 pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
9389 int doPostInstall(int status, int uid) {
9390 if (status != PackageManager.INSTALL_SUCCEEDED) {
9397 String getCodePath() {
9398 return (codeFile != null) ? codeFile.getAbsolutePath() : null;
9402 String getResourcePath() {
9403 return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
9407 String getLegacyNativeLibraryPath() {
9408 return (legacyNativeLibraryPath != null) ? legacyNativeLibraryPath.getAbsolutePath() : null;
9411 private boolean cleanUp() {
9412 if (codeFile == null || !codeFile.exists()) {
9416 if (codeFile.isDirectory()) {
9417 FileUtils.deleteContents(codeFile);
9421 if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
9422 resourceFile.delete();
9425 if (legacyNativeLibraryPath != null && !FileUtils.contains(codeFile, legacyNativeLibraryPath)) {
9426 if (!FileUtils.deleteContents(legacyNativeLibraryPath)) {
9427 Slog.w(TAG, "Couldn't delete native library directory " + legacyNativeLibraryPath);
9429 legacyNativeLibraryPath.delete();
9435 void cleanUpResourcesLI() {
9436 // Try enumerating all code paths before deleting
9437 List<String> allCodePaths = Collections.EMPTY_LIST;
9438 if (codeFile != null && codeFile.exists()) {
9440 final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
9441 allCodePaths = pkg.getAllCodePaths();
9442 } catch (PackageParserException e) {
9443 // Ignored; we tried our best
9449 if (!allCodePaths.isEmpty()) {
9450 if (instructionSets == null) {
9451 throw new IllegalStateException("instructionSet == null");
9453 String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
9454 for (String codePath : allCodePaths) {
9455 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
9456 int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet);
9458 Slog.w(TAG, "Couldn't remove dex file for package: "
9459 + " at location " + codePath + ", retcode=" + retCode);
9460 // we don't consider this to be a failure of the core package deletion
9467 boolean doPostDeleteLI(boolean delete) {
9468 // XXX err, shouldn't we respect the delete flag?
9469 cleanUpResourcesLI();
9474 private boolean isAsecExternal(String cid) {
9475 final String asecPath = PackageHelper.getSdFilesystem(cid);
9476 return !asecPath.startsWith(mAsecInternalPath);
9479 private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws
9480 PackageManagerException {
9482 if (copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
9483 copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
9484 throw new PackageManagerException(copyRet, message);
9490 * Extract the MountService "container ID" from the full code path of an
9493 static String cidFromCodePath(String fullCodePath) {
9494 int eidx = fullCodePath.lastIndexOf("/");
9495 String subStr1 = fullCodePath.substring(0, eidx);
9496 int sidx = subStr1.lastIndexOf("/");
9497 return subStr1.substring(sidx+1, eidx);
9501 * Logic to handle installation of ASEC applications, including copying and
9504 class AsecInstallArgs extends InstallArgs {
9505 static final String RES_FILE_NAME = "pkg.apk";
9506 static final String PUBLIC_RES_FILE_NAME = "res.zip";
9510 String resourcePath;
9511 String legacyNativeLibraryDir;
9514 AsecInstallArgs(InstallParams params) {
9515 super(params.origin, params.observer, params.installFlags,
9516 params.installerPackageName, params.getManifestDigest(),
9517 params.getUser(), null /* instruction sets */,
9518 params.packageAbiOverride);
9521 /** Existing install */
9522 AsecInstallArgs(String fullCodePath, String[] instructionSets,
9523 boolean isExternal, boolean isForwardLocked) {
9524 super(OriginInfo.fromNothing(), null, (isExternal ? INSTALL_EXTERNAL : 0)
9525 | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
9526 instructionSets, null);
9527 // Hackily pretend we're still looking at a full code path
9528 if (!fullCodePath.endsWith(RES_FILE_NAME)) {
9529 fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
9532 // Extract cid from fullCodePath
9533 int eidx = fullCodePath.lastIndexOf("/");
9534 String subStr1 = fullCodePath.substring(0, eidx);
9535 int sidx = subStr1.lastIndexOf("/");
9536 cid = subStr1.substring(sidx+1, eidx);
9537 setMountPath(subStr1);
9540 AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
9541 super(OriginInfo.fromNothing(), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
9542 | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
9543 instructionSets, null);
9545 setMountPath(PackageHelper.getSdDir(cid));
9548 void createCopyFile() {
9549 cid = mInstallerService.allocateExternalStageCidLegacy();
9552 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
9553 final long sizeBytes = imcs.calculateInstalledSize(packagePath, isFwdLocked(),
9558 target = new UserEnvironment(UserHandle.USER_OWNER).getExternalStorageDirectory();
9560 target = Environment.getDataDirectory();
9563 final StorageManager storage = StorageManager.from(mContext);
9564 return (sizeBytes <= storage.getStorageBytesUntilLow(target));
9567 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
9568 if (origin.staged) {
9569 Slog.d(TAG, origin.cid + " already staged; skipping copy");
9571 setMountPath(PackageHelper.getSdDir(cid));
9572 return PackageManager.INSTALL_SUCCEEDED;
9579 * Pre-emptively destroy the container since it's destroyed if
9580 * copying fails due to it existing anyway.
9582 PackageHelper.destroySdDir(cid);
9585 final String newMountPath = imcs.copyPackageToContainer(
9586 origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
9587 isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
9589 if (newMountPath != null) {
9590 setMountPath(newMountPath);
9591 return PackageManager.INSTALL_SUCCEEDED;
9593 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9598 String getCodePath() {
9603 String getResourcePath() {
9604 return resourcePath;
9608 String getLegacyNativeLibraryPath() {
9609 return legacyNativeLibraryDir;
9612 int doPreInstall(int status) {
9613 if (status != PackageManager.INSTALL_SUCCEEDED) {
9614 // Destroy container
9615 PackageHelper.destroySdDir(cid);
9617 boolean mounted = PackageHelper.isContainerMounted(cid);
9619 String newMountPath = PackageHelper.mountSdDir(cid, getEncryptKey(),
9620 Process.SYSTEM_UID);
9621 if (newMountPath != null) {
9622 setMountPath(newMountPath);
9624 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9631 boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
9632 String newCacheId = getNextCodePath(oldCodePath, pkg.packageName, "/" + RES_FILE_NAME);
9633 String newMountPath = null;
9634 if (PackageHelper.isContainerMounted(cid)) {
9635 // Unmount the container
9636 if (!PackageHelper.unMountSdDir(cid)) {
9637 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
9641 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
9642 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
9643 " which might be stale. Will try to clean up.");
9644 // Clean up the stale container and proceed to recreate.
9645 if (!PackageHelper.destroySdDir(newCacheId)) {
9646 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
9649 // Successfully cleaned up stale container. Try to rename again.
9650 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
9651 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
9652 + " inspite of cleaning it up.");
9656 if (!PackageHelper.isContainerMounted(newCacheId)) {
9657 Slog.w(TAG, "Mounting container " + newCacheId);
9658 newMountPath = PackageHelper.mountSdDir(newCacheId,
9659 getEncryptKey(), Process.SYSTEM_UID);
9661 newMountPath = PackageHelper.getSdDir(newCacheId);
9663 if (newMountPath == null) {
9664 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
9667 Log.i(TAG, "Succesfully renamed " + cid +
9668 " to " + newCacheId +
9669 " at new path: " + newMountPath);
9672 final File beforeCodeFile = new File(packagePath);
9673 setMountPath(newMountPath);
9674 final File afterCodeFile = new File(packagePath);
9676 // Reflect the rename in scanned details
9677 pkg.codePath = afterCodeFile.getAbsolutePath();
9678 pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
9680 pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
9681 pkg.splitCodePaths);
9683 // Reflect the rename in app info
9684 pkg.applicationInfo.setCodePath(pkg.codePath);
9685 pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
9686 pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
9687 pkg.applicationInfo.setResourcePath(pkg.codePath);
9688 pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
9689 pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
9694 private void setMountPath(String mountPath) {
9695 final File mountFile = new File(mountPath);
9697 final File monolithicFile = new File(mountFile, RES_FILE_NAME);
9698 if (monolithicFile.exists()) {
9699 packagePath = monolithicFile.getAbsolutePath();
9700 if (isFwdLocked()) {
9701 resourcePath = new File(mountFile, PUBLIC_RES_FILE_NAME).getAbsolutePath();
9703 resourcePath = packagePath;
9706 packagePath = mountFile.getAbsolutePath();
9707 resourcePath = packagePath;
9710 legacyNativeLibraryDir = new File(mountFile, LIB_DIR_NAME).getAbsolutePath();
9713 int doPostInstall(int status, int uid) {
9714 if (status != PackageManager.INSTALL_SUCCEEDED) {
9717 final int groupOwner;
9718 final String protectedFile;
9719 if (isFwdLocked()) {
9720 groupOwner = UserHandle.getSharedAppGid(uid);
9721 protectedFile = RES_FILE_NAME;
9724 protectedFile = null;
9727 if (uid < Process.FIRST_APPLICATION_UID
9728 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
9729 Slog.e(TAG, "Failed to finalize " + cid);
9730 PackageHelper.destroySdDir(cid);
9731 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9734 boolean mounted = PackageHelper.isContainerMounted(cid);
9736 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
9742 private void cleanUp() {
9743 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
9745 // Destroy secure container
9746 PackageHelper.destroySdDir(cid);
9749 private List<String> getAllCodePaths() {
9750 final File codeFile = new File(getCodePath());
9751 if (codeFile != null && codeFile.exists()) {
9753 final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
9754 return pkg.getAllCodePaths();
9755 } catch (PackageParserException e) {
9756 // Ignored; we tried our best
9759 return Collections.EMPTY_LIST;
9762 void cleanUpResourcesLI() {
9763 // Enumerate all code paths before deleting
9764 cleanUpResourcesLI(getAllCodePaths());
9767 private void cleanUpResourcesLI(List<String> allCodePaths) {
9770 if (!allCodePaths.isEmpty()) {
9771 if (instructionSets == null) {
9772 throw new IllegalStateException("instructionSet == null");
9774 String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
9775 for (String codePath : allCodePaths) {
9776 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
9777 int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet);
9779 Slog.w(TAG, "Couldn't remove dex file for package: "
9780 + " at location " + codePath + ", retcode=" + retCode);
9781 // we don't consider this to be a failure of the core package deletion
9788 boolean matchContainer(String app) {
9789 if (cid.startsWith(app)) {
9795 String getPackageName() {
9796 return getAsecPackageName(cid);
9799 boolean doPostDeleteLI(boolean delete) {
9800 if (DEBUG_SD_INSTALL) Slog.i(TAG, "doPostDeleteLI() del=" + delete);
9801 final List<String> allCodePaths = getAllCodePaths();
9802 boolean mounted = PackageHelper.isContainerMounted(cid);
9805 if (PackageHelper.unMountSdDir(cid)) {
9809 if (!mounted && delete) {
9810 cleanUpResourcesLI(allCodePaths);
9817 if (isFwdLocked()) {
9818 if (!PackageHelper.fixSdPermissions(cid,
9819 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
9820 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9824 return PackageManager.INSTALL_SUCCEEDED;
9828 int doPostCopy(int uid) {
9829 if (isFwdLocked()) {
9830 if (uid < Process.FIRST_APPLICATION_UID
9831 || !PackageHelper.fixSdPermissions(cid, UserHandle.getSharedAppGid(uid),
9833 Slog.e(TAG, "Failed to finalize " + cid);
9834 PackageHelper.destroySdDir(cid);
9835 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9839 return PackageManager.INSTALL_SUCCEEDED;
9843 static String getAsecPackageName(String packageCid) {
9844 int idx = packageCid.lastIndexOf("-");
9848 return packageCid.substring(0, idx);
9851 // Utility method used to create code paths based on package name and available index.
9852 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
9855 // Fall back to default value of idx=1 if prefix is not
9856 // part of oldCodePath
9857 if (oldCodePath != null) {
9858 String subStr = oldCodePath;
9859 // Drop the suffix right away
9860 if (suffix != null && subStr.endsWith(suffix)) {
9861 subStr = subStr.substring(0, subStr.length() - suffix.length());
9863 // If oldCodePath already contains prefix find out the
9864 // ending index to either increment or decrement.
9865 int sidx = subStr.lastIndexOf(prefix);
9867 subStr = subStr.substring(sidx + prefix.length());
9868 if (subStr != null) {
9869 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
9870 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
9873 idx = Integer.parseInt(subStr);
9879 } catch(NumberFormatException e) {
9884 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
9885 return prefix + idxStr;
9888 private File getNextCodePath(String packageName) {
9892 result = new File(mAppInstallDir, packageName + "-" + suffix);
9894 } while (result.exists());
9898 // Utility method used to ignore ADD/REMOVE events
9899 // by directory observer.
9900 private static boolean ignoreCodePath(String fullPathStr) {
9901 String apkName = deriveCodePathName(fullPathStr);
9902 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
9903 if (idx != -1 && ((idx+1) < apkName.length())) {
9904 // Make sure the package ends with a numeral
9905 String version = apkName.substring(idx+1);
9907 Integer.parseInt(version);
9909 } catch (NumberFormatException e) {}
9914 // Utility method that returns the relative package path with respect
9915 // to the installation directory. Like say for /data/data/com.test-1.apk
9916 // string com.test-1 is returned.
9917 static String deriveCodePathName(String codePath) {
9918 if (codePath == null) {
9921 final File codeFile = new File(codePath);
9922 final String name = codeFile.getName();
9923 if (codeFile.isDirectory()) {
9925 } else if (name.endsWith(".apk") || name.endsWith(".tmp")) {
9926 final int lastDot = name.lastIndexOf('.');
9927 return name.substring(0, lastDot);
9929 Slog.w(TAG, "Odd, " + codePath + " doesn't look like an APK");
9934 class PackageInstalledInfo {
9937 // The set of users that originally had this package installed.
9939 // The set of users that now have this package installed.
9941 PackageParser.Package pkg;
9944 PackageRemovedInfo removedInfo;
9946 public void setError(int code, String msg) {
9952 public void setError(String msg, PackageParserException e) {
9953 returnCode = e.error;
9954 returnMsg = ExceptionUtils.getCompleteMessage(msg, e);
9955 Slog.w(TAG, msg, e);
9958 public void setError(String msg, PackageManagerException e) {
9959 returnCode = e.error;
9960 returnMsg = ExceptionUtils.getCompleteMessage(msg, e);
9961 Slog.w(TAG, msg, e);
9964 // In some error cases we want to convey more info back to the observer
9966 String origPermission;
9970 * Install a non-existing package.
9972 private void installNewPackageLI(PackageParser.Package pkg,
9973 int parseFlags, int scanFlags, UserHandle user,
9974 String installerPackageName, PackageInstalledInfo res) {
9975 // Remember this for later, in case we need to rollback this install
9976 String pkgName = pkg.packageName;
9978 if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
9979 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
9980 synchronized(mPackages) {
9981 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
9982 // A package with the same name is already installed, though
9983 // it has been renamed to an older name. The package we
9984 // are trying to install should be installed as an update to
9985 // the existing one, but that has not been requested, so bail.
9986 res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
9987 + " without first uninstalling package running as "
9988 + mSettings.mRenamedPackages.get(pkgName));
9991 if (mPackages.containsKey(pkgName)) {
9992 // Don't allow installation over an existing package with the same name.
9993 res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
9994 + " without first uninstalling.");
10000 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,
10001 System.currentTimeMillis(), user);
10003 updateSettingsLI(newPackage, installerPackageName, null, null, res);
10004 // delete the partially installed application. the data directory will have to be
10005 // restored if it was already existing
10006 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
10007 // remove package from internal structures. Note that we want deletePackageX to
10008 // delete the package data and cache directories that it created in
10009 // scanPackageLocked, unless those directories existed before we even tried to
10011 deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
10012 dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
10013 res.removedInfo, true);
10016 } catch (PackageManagerException e) {
10017 res.setError("Package couldn't be installed in " + pkg.codePath, e);
10021 private boolean checkUpgradeKeySetLP(PackageSetting oldPS, PackageParser.Package newPkg) {
10022 // Upgrade keysets are being used. Determine if new package has a superset of the
10024 long[] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets();
10025 KeySetManagerService ksms = mSettings.mKeySetManagerService;
10026 for (int i = 0; i < upgradeKeySets.length; i++) {
10027 Set<PublicKey> upgradeSet = ksms.getPublicKeysFromKeySetLPr(upgradeKeySets[i]);
10028 if (newPkg.mSigningKeys.containsAll(upgradeSet)) {
10035 private void replacePackageLI(PackageParser.Package pkg,
10036 int parseFlags, int scanFlags, UserHandle user,
10037 String installerPackageName, PackageInstalledInfo res) {
10038 PackageParser.Package oldPackage;
10039 String pkgName = pkg.packageName;
10041 boolean[] perUserInstalled;
10043 // First find the old package info and check signatures
10044 synchronized(mPackages) {
10045 oldPackage = mPackages.get(pkgName);
10046 if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
10047 PackageSetting ps = mSettings.mPackages.get(pkgName);
10048 if (ps == null || !ps.keySetData.isUsingUpgradeKeySets() || ps.sharedUser != null) {
10049 // default to original signature matching
10050 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
10051 != PackageManager.SIGNATURE_MATCH) {
10052 res.setError(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
10053 "New package has a different signature: " + pkgName);
10057 if(!checkUpgradeKeySetLP(ps, pkg)) {
10058 res.setError(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
10059 "New package not signed by keys specified by upgrade-keysets: "
10065 // In case of rollback, remember per-user/profile install state
10066 allUsers = sUserManager.getUserIds();
10067 perUserInstalled = new boolean[allUsers.length];
10068 for (int i = 0; i < allUsers.length; i++) {
10069 perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
10073 boolean sysPkg = (isSystemApp(oldPackage));
10075 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
10076 user, allUsers, perUserInstalled, installerPackageName, res);
10078 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
10079 user, allUsers, perUserInstalled, installerPackageName, res);
10083 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
10084 PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
10085 int[] allUsers, boolean[] perUserInstalled,
10086 String installerPackageName, PackageInstalledInfo res) {
10087 String pkgName = deletedPackage.packageName;
10088 boolean deletedPkg = true;
10089 boolean updatedSettings = false;
10091 if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
10093 long origUpdateTime;
10094 if (pkg.mExtras != null) {
10095 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
10097 origUpdateTime = 0;
10100 // First delete the existing package while retaining the data directory
10101 if (!deletePackageLI(pkgName, null, true, null, null, PackageManager.DELETE_KEEP_DATA,
10102 res.removedInfo, true)) {
10103 // If the existing package wasn't successfully deleted
10104 res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI");
10105 deletedPkg = false;
10107 // Successfully deleted the old package; proceed with replace.
10109 // If deleted package lived in a container, give users a chance to
10110 // relinquish resources before killing.
10111 if (isForwardLocked(deletedPackage) || isExternal(deletedPackage)) {
10112 if (DEBUG_INSTALL) {
10113 Slog.i(TAG, "upgrading pkg " + deletedPackage + " is ASEC-hosted -> UNAVAILABLE");
10115 final int[] uidArray = new int[] { deletedPackage.applicationInfo.uid };
10116 final ArrayList<String> pkgList = new ArrayList<String>(1);
10117 pkgList.add(deletedPackage.applicationInfo.packageName);
10118 sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
10121 deleteCodeCacheDirsLI(pkgName);
10123 final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags,
10124 scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
10125 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
10126 updatedSettings = true;
10127 } catch (PackageManagerException e) {
10128 res.setError("Package couldn't be installed in " + pkg.codePath, e);
10132 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
10133 // remove package from internal structures. Note that we want deletePackageX to
10134 // delete the package data and cache directories that it created in
10135 // scanPackageLocked, unless those directories existed before we even tried to
10137 if(updatedSettings) {
10138 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
10140 pkgName, null, true, allUsers, perUserInstalled,
10141 PackageManager.DELETE_KEEP_DATA,
10142 res.removedInfo, true);
10144 // Since we failed to install the new package we need to restore the old
10145 // package that we deleted.
10147 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
10148 File restoreFile = new File(deletedPackage.codePath);
10149 // Parse old package
10150 boolean oldOnSd = isExternal(deletedPackage);
10151 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
10152 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
10153 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
10154 int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;
10156 scanPackageLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime, null);
10157 } catch (PackageManagerException e) {
10158 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: "
10162 // Restore of old package succeeded. Update permissions.
10164 synchronized (mPackages) {
10165 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
10166 UPDATE_PERMISSIONS_ALL);
10167 // can downgrade to reader
10168 mSettings.writeLPr();
10170 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
10175 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
10176 PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
10177 int[] allUsers, boolean[] perUserInstalled,
10178 String installerPackageName, PackageInstalledInfo res) {
10179 if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
10180 + ", old=" + deletedPackage);
10181 boolean disabledSystem = false;
10182 boolean updatedSettings = false;
10183 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
10184 if ((deletedPackage.applicationInfo.flags&ApplicationInfo.FLAG_PRIVILEGED) != 0) {
10185 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
10187 String packageName = deletedPackage.packageName;
10188 if (packageName == null) {
10189 res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE,
10190 "Attempt to delete null packageName.");
10193 PackageParser.Package oldPkg;
10194 PackageSetting oldPkgSetting;
10196 synchronized (mPackages) {
10197 oldPkg = mPackages.get(packageName);
10198 oldPkgSetting = mSettings.mPackages.get(packageName);
10199 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
10200 (oldPkgSetting == null)) {
10201 res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE,
10202 "Couldn't find package:" + packageName + " information");
10207 killApplication(packageName, oldPkg.applicationInfo.uid, "replace sys pkg");
10209 res.removedInfo.uid = oldPkg.applicationInfo.uid;
10210 res.removedInfo.removedPackage = packageName;
10211 // Remove existing system package
10212 removePackageLI(oldPkgSetting, true);
10214 synchronized (mPackages) {
10215 disabledSystem = mSettings.disableSystemPackageLPw(packageName);
10216 if (!disabledSystem && deletedPackage != null) {
10217 // We didn't need to disable the .apk as a current system package,
10218 // which means we are replacing another update that is already
10219 // installed. We need to make sure to delete the older one's .apk.
10220 res.removedInfo.args = createInstallArgsForExisting(0,
10221 deletedPackage.applicationInfo.getCodePath(),
10222 deletedPackage.applicationInfo.getResourcePath(),
10223 deletedPackage.applicationInfo.nativeLibraryRootDir,
10224 getAppDexInstructionSets(deletedPackage.applicationInfo));
10226 res.removedInfo.args = null;
10230 // Successfully disabled the old package. Now proceed with re-installation
10231 deleteCodeCacheDirsLI(packageName);
10233 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
10234 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
10236 PackageParser.Package newPackage = null;
10238 newPackage = scanPackageLI(pkg, parseFlags, scanFlags, 0, user);
10239 if (newPackage.mExtras != null) {
10240 final PackageSetting newPkgSetting = (PackageSetting) newPackage.mExtras;
10241 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
10242 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
10244 // is the update attempting to change shared user? that isn't going to work...
10245 if (oldPkgSetting.sharedUser != newPkgSetting.sharedUser) {
10246 res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
10247 "Forbidding shared user change from " + oldPkgSetting.sharedUser
10248 + " to " + newPkgSetting.sharedUser);
10249 updatedSettings = true;
10253 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
10254 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
10255 updatedSettings = true;
10258 } catch (PackageManagerException e) {
10259 res.setError("Package couldn't be installed in " + pkg.codePath, e);
10262 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
10263 // Re installation failed. Restore old information
10264 // Remove new pkg information
10265 if (newPackage != null) {
10266 removeInstalledPackageLI(newPackage, true);
10268 // Add back the old system package
10270 scanPackageLI(oldPkg, parseFlags, SCAN_UPDATE_SIGNATURE, 0, user);
10271 } catch (PackageManagerException e) {
10272 Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
10274 // Restore the old system information in Settings
10275 synchronized (mPackages) {
10276 if (disabledSystem) {
10277 mSettings.enableSystemPackageLPw(packageName);
10279 if (updatedSettings) {
10280 mSettings.setInstallerPackageName(packageName,
10281 oldPkgSetting.installerPackageName);
10283 mSettings.writeLPr();
10288 private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
10289 int[] allUsers, boolean[] perUserInstalled,
10290 PackageInstalledInfo res) {
10291 String pkgName = newPackage.packageName;
10292 synchronized (mPackages) {
10293 //write settings. the installStatus will be incomplete at this stage.
10294 //note that the new package setting would have already been
10295 //added to mPackages. It hasn't been persisted yet.
10296 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
10297 mSettings.writeLPr();
10300 if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.codePath);
10302 synchronized (mPackages) {
10303 updatePermissionsLPw(newPackage.packageName, newPackage,
10304 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
10305 ? UPDATE_PERMISSIONS_ALL : 0));
10306 // For system-bundled packages, we assume that installing an upgraded version
10307 // of the package implies that the user actually wants to run that new code,
10308 // so we enable the package.
10309 if (isSystemApp(newPackage)) {
10310 // NB: implicit assumption that system package upgrades apply to all users
10311 if (DEBUG_INSTALL) {
10312 Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName);
10314 PackageSetting ps = mSettings.mPackages.get(pkgName);
10316 if (res.origUsers != null) {
10317 for (int userHandle : res.origUsers) {
10318 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT,
10319 userHandle, installerPackageName);
10322 // Also convey the prior install/uninstall state
10323 if (allUsers != null && perUserInstalled != null) {
10324 for (int i = 0; i < allUsers.length; i++) {
10325 if (DEBUG_INSTALL) {
10326 Slog.d(TAG, " user " + allUsers[i]
10327 + " => " + perUserInstalled[i]);
10329 ps.setInstalled(perUserInstalled[i], allUsers[i]);
10331 // these install state changes will be persisted in the
10332 // upcoming call to mSettings.writeLPr().
10336 res.name = pkgName;
10337 res.uid = newPackage.applicationInfo.uid;
10338 res.pkg = newPackage;
10339 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
10340 mSettings.setInstallerPackageName(pkgName, installerPackageName);
10341 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
10342 //to update install status
10343 mSettings.writeLPr();
10347 private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
10348 final int installFlags = args.installFlags;
10349 String installerPackageName = args.installerPackageName;
10350 File tmpPackageFile = new File(args.getCodePath());
10351 boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
10352 boolean onSd = ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0);
10353 boolean replace = false;
10354 final int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
10355 // Result object to be returned
10356 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
10358 if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
10359 // Retrieve PackageSettings and parse package
10360 final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
10361 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
10362 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
10363 PackageParser pp = new PackageParser();
10364 pp.setSeparateProcesses(mSeparateProcesses);
10365 pp.setDisplayMetrics(mMetrics);
10367 final PackageParser.Package pkg;
10369 pkg = pp.parsePackage(tmpPackageFile, parseFlags);
10370 } catch (PackageParserException e) {
10371 res.setError("Failed parse during installPackageLI", e);
10375 // Mark that we have an install time CPU ABI override.
10376 pkg.cpuAbiOverride = args.abiOverride;
10378 String pkgName = res.name = pkg.packageName;
10379 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
10380 if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
10381 res.setError(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
10387 pp.collectCertificates(pkg, parseFlags);
10388 pp.collectManifestDigest(pkg);
10389 } catch (PackageParserException e) {
10390 res.setError("Failed collect during installPackageLI", e);
10394 /* If the installer passed in a manifest digest, compare it now. */
10395 if (args.manifestDigest != null) {
10396 if (DEBUG_INSTALL) {
10397 final String parsedManifest = pkg.manifestDigest == null ? "null"
10398 : pkg.manifestDigest.toString();
10399 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
10403 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
10404 res.setError(INSTALL_FAILED_PACKAGE_CHANGED, "Manifest digest changed");
10407 } else if (DEBUG_INSTALL) {
10408 final String parsedManifest = pkg.manifestDigest == null
10409 ? "null" : pkg.manifestDigest.toString();
10410 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
10413 // Get rid of all references to package scan path via parser.
10415 String oldCodePath = null;
10416 boolean systemApp = false;
10417 synchronized (mPackages) {
10418 // Check if installing already existing package
10419 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
10420 String oldName = mSettings.mRenamedPackages.get(pkgName);
10421 if (pkg.mOriginalPackages != null
10422 && pkg.mOriginalPackages.contains(oldName)
10423 && mPackages.containsKey(oldName)) {
10424 // This package is derived from an original package,
10425 // and this device has been updating from that original
10426 // name. We must continue using the original name, so
10427 // rename the new package here.
10428 pkg.setPackageName(oldName);
10429 pkgName = pkg.packageName;
10431 if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
10432 + oldName + " pkgName=" + pkgName);
10433 } else if (mPackages.containsKey(pkgName)) {
10434 // This package, under its official name, already exists
10435 // on the device; we should replace it.
10437 if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
10441 PackageSetting ps = mSettings.mPackages.get(pkgName);
10443 if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
10445 // Quick sanity check that we're signed correctly if updating;
10446 // we'll check this again later when scanning, but we want to
10447 // bail early here before tripping over redefined permissions.
10448 if (!ps.keySetData.isUsingUpgradeKeySets() || ps.sharedUser != null) {
10450 verifySignaturesLP(ps, pkg);
10451 } catch (PackageManagerException e) {
10452 res.setError(e.error, e.getMessage());
10456 if (!checkUpgradeKeySetLP(ps, pkg)) {
10457 res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
10458 + pkg.packageName + " upgrade keys do not match the "
10459 + "previously installed version");
10464 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
10465 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
10466 systemApp = (ps.pkg.applicationInfo.flags &
10467 ApplicationInfo.FLAG_SYSTEM) != 0;
10469 res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
10472 // Check whether the newly-scanned package wants to define an already-defined perm
10473 int N = pkg.permissions.size();
10474 for (int i = N-1; i >= 0; i--) {
10475 PackageParser.Permission perm = pkg.permissions.get(i);
10476 BasePermission bp = mSettings.mPermissions.get(perm.info.name);
10478 // If the defining package is signed with our cert, it's okay. This
10479 // also includes the "updating the same package" case, of course.
10480 // "updating same package" could also involve key-rotation.
10481 final boolean sigsOk;
10482 if (!bp.sourcePackage.equals(pkg.packageName)
10483 || !(bp.packageSetting instanceof PackageSetting)
10484 || !bp.packageSetting.keySetData.isUsingUpgradeKeySets()
10485 || ((PackageSetting) bp.packageSetting).sharedUser != null) {
10486 sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures,
10487 pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
10489 sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg);
10492 // If the owning package is the system itself, we log but allow
10493 // install to proceed; we fail the install on all other permission
10495 if (!bp.sourcePackage.equals("android")) {
10496 res.setError(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package "
10497 + pkg.packageName + " attempting to redeclare permission "
10498 + perm.info.name + " already owned by " + bp.sourcePackage);
10499 res.origPermission = perm.info.name;
10500 res.origPackage = bp.sourcePackage;
10503 Slog.w(TAG, "Package " + pkg.packageName
10504 + " attempting to redeclare system permission "
10505 + perm.info.name + "; ignoring new declaration");
10506 pkg.permissions.remove(i);
10514 if (systemApp && onSd) {
10515 // Disable updates to system apps on sdcard
10516 res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
10517 "Cannot install updates to system apps on sdcard");
10521 if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
10522 res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
10527 replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
10528 installerPackageName, res);
10530 installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
10531 args.user, installerPackageName, res);
10533 synchronized (mPackages) {
10534 final PackageSetting ps = mSettings.mPackages.get(pkgName);
10536 res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
10541 private static boolean isForwardLocked(PackageParser.Package pkg) {
10542 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
10545 private static boolean isForwardLocked(ApplicationInfo info) {
10546 return (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
10549 private boolean isForwardLocked(PackageSetting ps) {
10550 return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
10553 private static boolean isMultiArch(PackageSetting ps) {
10554 return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0;
10557 private static boolean isMultiArch(ApplicationInfo info) {
10558 return (info.flags & ApplicationInfo.FLAG_MULTIARCH) != 0;
10561 private static boolean isExternal(PackageParser.Package pkg) {
10562 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
10565 private static boolean isExternal(PackageSetting ps) {
10566 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
10569 private static boolean isExternal(ApplicationInfo info) {
10570 return (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
10573 private static boolean isSystemApp(PackageParser.Package pkg) {
10574 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
10577 private static boolean isPrivilegedApp(PackageParser.Package pkg) {
10578 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
10581 private static boolean isSystemApp(ApplicationInfo info) {
10582 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
10585 private static boolean isSystemApp(PackageSetting ps) {
10586 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
10589 private static boolean isUpdatedSystemApp(PackageSetting ps) {
10590 return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
10593 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
10594 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
10597 private static boolean isUpdatedSystemApp(ApplicationInfo info) {
10598 return (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
10601 private int packageFlagsToInstallFlags(PackageSetting ps) {
10602 int installFlags = 0;
10603 if (isExternal(ps)) {
10604 installFlags |= PackageManager.INSTALL_EXTERNAL;
10606 if (isForwardLocked(ps)) {
10607 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
10609 return installFlags;
10612 private void deleteTempPackageFiles() {
10613 final FilenameFilter filter = new FilenameFilter() {
10614 public boolean accept(File dir, String name) {
10615 return name.startsWith("vmdl") && name.endsWith(".tmp");
10618 for (File file : mDrmAppPrivateInstallDir.listFiles(filter)) {
10624 public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int userId,
10626 deletePackage(packageName, new LegacyPackageDeleteObserver(observer).getBinder(), userId,
10631 public void deletePackage(final String packageName,
10632 final IPackageDeleteObserver2 observer, final int userId, final int flags) {
10633 mContext.enforceCallingOrSelfPermission(
10634 android.Manifest.permission.DELETE_PACKAGES, null);
10635 final int uid = Binder.getCallingUid();
10636 if (UserHandle.getUserId(uid) != userId) {
10637 mContext.enforceCallingPermission(
10638 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
10639 "deletePackage for user " + userId);
10641 if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
10643 observer.onPackageDeleted(packageName,
10644 PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
10645 } catch (RemoteException re) {
10650 boolean uninstallBlocked = false;
10651 if ((flags & PackageManager.DELETE_ALL_USERS) != 0) {
10652 int[] users = sUserManager.getUserIds();
10653 for (int i = 0; i < users.length; ++i) {
10654 if (getBlockUninstallForUser(packageName, users[i])) {
10655 uninstallBlocked = true;
10660 uninstallBlocked = getBlockUninstallForUser(packageName, userId);
10662 if (uninstallBlocked) {
10664 observer.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_OWNER_BLOCKED,
10666 } catch (RemoteException re) {
10671 if (DEBUG_REMOVE) {
10672 Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
10674 // Queue up an async operation since the package deletion may take a little while.
10675 mHandler.post(new Runnable() {
10676 public void run() {
10677 mHandler.removeCallbacks(this);
10678 final int returnCode = deletePackageX(packageName, userId, flags);
10679 if (observer != null) {
10681 observer.onPackageDeleted(packageName, returnCode, null);
10682 } catch (RemoteException e) {
10683 Log.i(TAG, "Observer no longer exists.");
10690 private boolean isPackageDeviceAdmin(String packageName, int userId) {
10691 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
10692 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
10695 if (dpm.isDeviceOwner(packageName)) {
10699 if (userId == UserHandle.USER_ALL) {
10700 users = sUserManager.getUserIds();
10702 users = new int[]{userId};
10704 for (int i = 0; i < users.length; ++i) {
10705 if (dpm.packageHasActiveAdmins(packageName, users[i])) {
10710 } catch (RemoteException e) {
10716 * This method is an internal method that could be get invoked either
10717 * to delete an installed package or to clean up a failed installation.
10718 * After deleting an installed package, a broadcast is sent to notify any
10719 * listeners that the package has been installed. For cleaning up a failed
10720 * installation, the broadcast is not necessary since the package's
10721 * installation wouldn't have sent the initial broadcast either
10722 * The key steps in deleting a package are
10723 * deleting the package information in internal structures like mPackages,
10724 * deleting the packages base directories through installd
10725 * updating mSettings to reflect current status
10726 * persisting settings for later use
10727 * sending a broadcast if necessary
10729 private int deletePackageX(String packageName, int userId, int flags) {
10730 final PackageRemovedInfo info = new PackageRemovedInfo();
10733 final UserHandle removeForUser = (flags & PackageManager.DELETE_ALL_USERS) != 0
10734 ? UserHandle.ALL : new UserHandle(userId);
10736 if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {
10737 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
10738 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
10741 boolean removedForAllUsers = false;
10742 boolean systemUpdate = false;
10744 // for the uninstall-updates case and restricted profiles, remember the per-
10745 // userhandle installed state
10747 boolean[] perUserInstalled;
10748 synchronized (mPackages) {
10749 PackageSetting ps = mSettings.mPackages.get(packageName);
10750 allUsers = sUserManager.getUserIds();
10751 perUserInstalled = new boolean[allUsers.length];
10752 for (int i = 0; i < allUsers.length; i++) {
10753 perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
10757 synchronized (mInstallLock) {
10758 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
10759 res = deletePackageLI(packageName, removeForUser,
10760 true, allUsers, perUserInstalled,
10761 flags | REMOVE_CHATTY, info, true);
10762 systemUpdate = info.isRemovedPackageSystemUpdate;
10763 if (res && !systemUpdate && mPackages.get(packageName) == null) {
10764 removedForAllUsers = true;
10766 if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate
10767 + " removedForAllUsers=" + removedForAllUsers);
10771 info.sendBroadcast(true, systemUpdate, removedForAllUsers);
10773 // If the removed package was a system update, the old system package
10774 // was re-enabled; we need to broadcast this information
10775 if (systemUpdate) {
10776 Bundle extras = new Bundle(1);
10777 extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
10778 ? info.removedAppId : info.uid);
10779 extras.putBoolean(Intent.EXTRA_REPLACING, true);
10781 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
10782 extras, null, null, null);
10783 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
10784 extras, null, null, null);
10785 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
10786 null, packageName, null, null);
10789 // Force a gc here.
10790 Runtime.getRuntime().gc();
10791 // Delete the resources here after sending the broadcast to let
10792 // other processes clean up before deleting resources.
10793 if (info.args != null) {
10794 synchronized (mInstallLock) {
10795 info.args.doPostDeleteLI(true);
10799 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
10802 static class PackageRemovedInfo {
10803 String removedPackage;
10805 int removedAppId = -1;
10806 int[] removedUsers = null;
10807 boolean isRemovedPackageSystemUpdate = false;
10808 // Clean up resources deleted packages.
10809 InstallArgs args = null;
10811 void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
10812 Bundle extras = new Bundle(1);
10813 extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
10814 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
10816 extras.putBoolean(Intent.EXTRA_REPLACING, true);
10818 extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
10819 if (removedPackage != null) {
10820 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
10821 extras, null, null, removedUsers);
10822 if (fullRemove && !replacing) {
10823 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
10824 extras, null, null, removedUsers);
10827 if (removedAppId >= 0) {
10828 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
10835 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
10836 * flag is not set, the data directory is removed as well.
10837 * make sure this flag is set for partially installed apps. If not its meaningless to
10838 * delete a partially installed application.
10840 private void removePackageDataLI(PackageSetting ps,
10841 int[] allUserHandles, boolean[] perUserInstalled,
10842 PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
10843 String packageName = ps.name;
10844 if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
10845 removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
10846 // Retrieve object to delete permissions for shared user later on
10847 final PackageSetting deletedPs;
10849 synchronized (mPackages) {
10850 deletedPs = mSettings.mPackages.get(packageName);
10851 if (outInfo != null) {
10852 outInfo.removedPackage = packageName;
10853 outInfo.removedUsers = deletedPs != null
10854 ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
10858 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
10859 removeDataDirsLI(packageName);
10860 schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
10863 synchronized (mPackages) {
10864 if (deletedPs != null) {
10865 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
10866 if (outInfo != null) {
10867 mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
10868 outInfo.removedAppId = mSettings.removePackageLPw(packageName);
10870 if (deletedPs != null) {
10871 updatePermissionsLPw(deletedPs.name, null, 0);
10872 if (deletedPs.sharedUser != null) {
10873 // remove permissions associated with package
10874 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
10877 clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
10879 // make sure to preserve per-user disabled state if this removal was just
10880 // a downgrade of a system app to the factory package
10881 if (allUserHandles != null && perUserInstalled != null) {
10882 if (DEBUG_REMOVE) {
10883 Slog.d(TAG, "Propagating install state across downgrade");
10885 for (int i = 0; i < allUserHandles.length; i++) {
10886 if (DEBUG_REMOVE) {
10887 Slog.d(TAG, " user " + allUserHandles[i]
10888 + " => " + perUserInstalled[i]);
10890 ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
10894 // can downgrade to reader
10895 if (writeSettings) {
10896 // Save settings now
10897 mSettings.writeLPr();
10900 if (outInfo != null) {
10901 // A user ID was deleted here. Go through all users and remove it
10903 removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId);
10907 static boolean locationIsPrivileged(File path) {
10909 final String privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app")
10910 .getCanonicalPath();
10911 return path.getCanonicalPath().startsWith(privilegedAppDir);
10912 } catch (IOException e) {
10913 Slog.e(TAG, "Unable to access code path " + path);
10919 * Tries to delete system package.
10921 private boolean deleteSystemPackageLI(PackageSetting newPs,
10922 int[] allUserHandles, boolean[] perUserInstalled,
10923 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
10924 final boolean applyUserRestrictions
10925 = (allUserHandles != null) && (perUserInstalled != null);
10926 PackageSetting disabledPs = null;
10927 // Confirm if the system package has been updated
10928 // An updated system app can be deleted. This will also have to restore
10929 // the system pkg from system partition
10931 synchronized (mPackages) {
10932 disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
10934 if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + newPs
10935 + " disabledPs=" + disabledPs);
10936 if (disabledPs == null) {
10937 Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
10939 } else if (DEBUG_REMOVE) {
10940 Slog.d(TAG, "Deleting system pkg from data partition");
10942 if (DEBUG_REMOVE) {
10943 if (applyUserRestrictions) {
10944 Slog.d(TAG, "Remembering install states:");
10945 for (int i = 0; i < allUserHandles.length; i++) {
10946 Slog.d(TAG, " u=" + allUserHandles[i] + " inst=" + perUserInstalled[i]);
10950 // Delete the updated package
10951 outInfo.isRemovedPackageSystemUpdate = true;
10952 if (disabledPs.versionCode < newPs.versionCode) {
10953 // Delete data for downgrades
10954 flags &= ~PackageManager.DELETE_KEEP_DATA;
10956 // Preserve data by setting flag
10957 flags |= PackageManager.DELETE_KEEP_DATA;
10959 boolean ret = deleteInstalledPackageLI(newPs, true, flags,
10960 allUserHandles, perUserInstalled, outInfo, writeSettings);
10965 synchronized (mPackages) {
10966 // Reinstate the old system package
10967 mSettings.enableSystemPackageLPw(newPs.name);
10968 // Remove any native libraries from the upgraded package.
10969 NativeLibraryHelper.removeNativeBinariesLI(newPs.legacyNativeLibraryPathString);
10971 // Install the system package
10972 if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
10973 int parseFlags = PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM;
10974 if (locationIsPrivileged(disabledPs.codePath)) {
10975 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
10978 final PackageParser.Package newPkg;
10980 newPkg = scanPackageLI(disabledPs.codePath, parseFlags, SCAN_NO_PATHS, 0, null);
10981 } catch (PackageManagerException e) {
10982 Slog.w(TAG, "Failed to restore system package:" + newPs.name + ": " + e.getMessage());
10987 synchronized (mPackages) {
10988 PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
10989 updatePermissionsLPw(newPkg.packageName, newPkg,
10990 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
10991 if (applyUserRestrictions) {
10992 if (DEBUG_REMOVE) {
10993 Slog.d(TAG, "Propagating install state across reinstall");
10995 for (int i = 0; i < allUserHandles.length; i++) {
10996 if (DEBUG_REMOVE) {
10997 Slog.d(TAG, " user " + allUserHandles[i]
10998 + " => " + perUserInstalled[i]);
11000 ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
11002 // Regardless of writeSettings we need to ensure that this restriction
11003 // state propagation is persisted
11004 mSettings.writeAllUsersPackageRestrictionsLPr();
11006 // can downgrade to reader here
11007 if (writeSettings) {
11008 mSettings.writeLPr();
11014 private boolean deleteInstalledPackageLI(PackageSetting ps,
11015 boolean deleteCodeAndResources, int flags,
11016 int[] allUserHandles, boolean[] perUserInstalled,
11017 PackageRemovedInfo outInfo, boolean writeSettings) {
11018 if (outInfo != null) {
11019 outInfo.uid = ps.appId;
11022 // Delete package data from internal structures and also remove data if flag is set
11023 removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);
11025 // Delete application code and resources
11026 if (deleteCodeAndResources && (outInfo != null)) {
11027 outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
11028 ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
11029 getAppDexInstructionSets(ps));
11030 if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
11036 public boolean setBlockUninstallForUser(String packageName, boolean blockUninstall,
11038 mContext.enforceCallingOrSelfPermission(
11039 android.Manifest.permission.DELETE_PACKAGES, null);
11040 synchronized (mPackages) {
11041 PackageSetting ps = mSettings.mPackages.get(packageName);
11043 Log.i(TAG, "Package doesn't exist in set block uninstall " + packageName);
11046 if (!ps.getInstalled(userId)) {
11047 // Can't block uninstall for an app that is not installed or enabled.
11048 Log.i(TAG, "Package not installed in set block uninstall " + packageName);
11051 ps.setBlockUninstall(blockUninstall, userId);
11052 mSettings.writePackageRestrictionsLPr(userId);
11058 public boolean getBlockUninstallForUser(String packageName, int userId) {
11059 synchronized (mPackages) {
11060 PackageSetting ps = mSettings.mPackages.get(packageName);
11062 Log.i(TAG, "Package doesn't exist in get block uninstall " + packageName);
11065 return ps.getBlockUninstall(userId);
11070 * This method handles package deletion in general
11072 private boolean deletePackageLI(String packageName, UserHandle user,
11073 boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,
11074 int flags, PackageRemovedInfo outInfo,
11075 boolean writeSettings) {
11076 if (packageName == null) {
11077 Slog.w(TAG, "Attempt to delete null packageName.");
11080 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
11082 boolean dataOnly = false;
11083 int removeUser = -1;
11085 synchronized (mPackages) {
11086 ps = mSettings.mPackages.get(packageName);
11088 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
11091 if ((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
11092 && user.getIdentifier() != UserHandle.USER_ALL) {
11093 // The caller is asking that the package only be deleted for a single
11094 // user. To do this, we just mark its uninstalled state and delete
11095 // its data. If this is a system app, we only allow this to happen if
11096 // they have set the special DELETE_SYSTEM_APP which requests different
11097 // semantics than normal for uninstalling system apps.
11098 if (DEBUG_REMOVE) Slog.d(TAG, "Only deleting for single user");
11099 ps.setUserState(user.getIdentifier(),
11100 COMPONENT_ENABLED_STATE_DEFAULT,
11103 true, //notLaunched
11106 false // blockUninstall
11108 if (!isSystemApp(ps)) {
11109 if (ps.isAnyInstalled(sUserManager.getUserIds())) {
11110 // Other user still have this package installed, so all
11111 // we need to do is clear this user's data and save that
11112 // it is uninstalled.
11113 if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
11114 removeUser = user.getIdentifier();
11116 mSettings.writePackageRestrictionsLPr(removeUser);
11118 // We need to set it back to 'installed' so the uninstall
11119 // broadcasts will be sent correctly.
11120 if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
11121 ps.setInstalled(true, user.getIdentifier());
11124 // This is a system app, so we assume that the
11125 // other users still have this package installed, so all
11126 // we need to do is clear this user's data and save that
11127 // it is uninstalled.
11128 if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
11129 removeUser = user.getIdentifier();
11131 mSettings.writePackageRestrictionsLPr(removeUser);
11136 if (removeUser >= 0) {
11137 // From above, we determined that we are deleting this only
11138 // for a single user. Continue the work here.
11139 if (DEBUG_REMOVE) Slog.d(TAG, "Updating install state for user: " + removeUser);
11140 if (outInfo != null) {
11141 outInfo.removedPackage = packageName;
11142 outInfo.removedAppId = appId;
11143 outInfo.removedUsers = new int[] {removeUser};
11145 mInstaller.clearUserData(packageName, removeUser);
11146 removeKeystoreDataIfNeeded(removeUser, appId);
11147 schedulePackageCleaning(packageName, removeUser, false);
11152 // Delete application data first
11153 if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
11154 removePackageDataLI(ps, null, null, outInfo, flags, writeSettings);
11158 boolean ret = false;
11159 if (isSystemApp(ps)) {
11160 if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
11161 // When an updated system application is deleted we delete the existing resources as well and
11162 // fall back to existing code in system partition
11163 ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,
11164 flags, outInfo, writeSettings);
11166 if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
11167 // Kill application pre-emptively especially for apps on sd.
11168 killApplication(packageName, ps.appId, "uninstall pkg");
11169 ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,
11170 allUserHandles, perUserInstalled,
11171 outInfo, writeSettings);
11177 private final class ClearStorageConnection implements ServiceConnection {
11178 IMediaContainerService mContainerService;
11181 public void onServiceConnected(ComponentName name, IBinder service) {
11182 synchronized (this) {
11183 mContainerService = IMediaContainerService.Stub.asInterface(service);
11189 public void onServiceDisconnected(ComponentName name) {
11193 private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
11194 final boolean mounted;
11195 if (Environment.isExternalStorageEmulated()) {
11198 final String status = Environment.getExternalStorageState();
11200 mounted = status.equals(Environment.MEDIA_MOUNTED)
11201 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
11208 final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
11210 if (userId == UserHandle.USER_ALL) {
11211 users = sUserManager.getUserIds();
11213 users = new int[] { userId };
11215 final ClearStorageConnection conn = new ClearStorageConnection();
11216 if (mContext.bindServiceAsUser(
11217 containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
11219 for (int curUser : users) {
11220 long timeout = SystemClock.uptimeMillis() + 5000;
11221 synchronized (conn) {
11222 long now = SystemClock.uptimeMillis();
11223 while (conn.mContainerService == null && now < timeout) {
11225 conn.wait(timeout - now);
11226 } catch (InterruptedException e) {
11230 if (conn.mContainerService == null) {
11234 final UserEnvironment userEnv = new UserEnvironment(curUser);
11235 clearDirectory(conn.mContainerService,
11236 userEnv.buildExternalStorageAppCacheDirs(packageName));
11238 clearDirectory(conn.mContainerService,
11239 userEnv.buildExternalStorageAppDataDirs(packageName));
11240 clearDirectory(conn.mContainerService,
11241 userEnv.buildExternalStorageAppMediaDirs(packageName));
11245 mContext.unbindService(conn);
11251 public void clearApplicationUserData(final String packageName,
11252 final IPackageDataObserver observer, final int userId) {
11253 mContext.enforceCallingOrSelfPermission(
11254 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
11255 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "clear application data");
11256 // Queue up an async operation since the package deletion may take a little while.
11257 mHandler.post(new Runnable() {
11258 public void run() {
11259 mHandler.removeCallbacks(this);
11260 final boolean succeeded;
11261 synchronized (mInstallLock) {
11262 succeeded = clearApplicationUserDataLI(packageName, userId);
11264 clearExternalStorageDataSync(packageName, userId, true);
11266 // invoke DeviceStorageMonitor's update method to clear any notifications
11267 DeviceStorageMonitorInternal
11268 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
11273 if(observer != null) {
11275 observer.onRemoveCompleted(packageName, succeeded);
11276 } catch (RemoteException e) {
11277 Log.i(TAG, "Observer no longer exists.");
11279 } //end if observer
11284 private boolean clearApplicationUserDataLI(String packageName, int userId) {
11285 if (packageName == null) {
11286 Slog.w(TAG, "Attempt to delete null packageName.");
11290 // Try finding details about the requested package
11291 PackageParser.Package pkg;
11292 synchronized (mPackages) {
11293 pkg = mPackages.get(packageName);
11295 final PackageSetting ps = mSettings.mPackages.get(packageName);
11303 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
11306 // Always delete data directories for package, even if we found no other
11307 // record of app. This helps users recover from UID mismatches without
11308 // resorting to a full data wipe.
11309 int retCode = mInstaller.clearUserData(packageName, userId);
11311 Slog.w(TAG, "Couldn't remove cache files for package: " + packageName);
11319 if (pkg != null && pkg.applicationInfo != null) {
11320 final int appId = pkg.applicationInfo.uid;
11321 removeKeystoreDataIfNeeded(userId, appId);
11324 // Create a native library symlink only if we have native libraries
11325 // and if the native libraries are 32 bit libraries. We do not provide
11326 // this symlink for 64 bit libraries.
11327 if (pkg != null && pkg.applicationInfo.primaryCpuAbi != null &&
11328 !VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
11329 final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
11330 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName, nativeLibPath, userId) < 0) {
11331 Slog.w(TAG, "Failed linking native library dir");
11340 * Remove entries from the keystore daemon. Will only remove it if the
11341 * {@code appId} is valid.
11343 private static void removeKeystoreDataIfNeeded(int userId, int appId) {
11348 final KeyStore keyStore = KeyStore.getInstance();
11349 if (keyStore != null) {
11350 if (userId == UserHandle.USER_ALL) {
11351 for (final int individual : sUserManager.getUserIds()) {
11352 keyStore.clearUid(UserHandle.getUid(individual, appId));
11355 keyStore.clearUid(UserHandle.getUid(userId, appId));
11358 Slog.w(TAG, "Could not contact keystore to clear entries for app id " + appId);
11363 public void deleteApplicationCacheFiles(final String packageName,
11364 final IPackageDataObserver observer) {
11365 mContext.enforceCallingOrSelfPermission(
11366 android.Manifest.permission.DELETE_CACHE_FILES, null);
11367 // Queue up an async operation since the package deletion may take a little while.
11368 final int userId = UserHandle.getCallingUserId();
11369 mHandler.post(new Runnable() {
11370 public void run() {
11371 mHandler.removeCallbacks(this);
11372 final boolean succeded;
11373 synchronized (mInstallLock) {
11374 succeded = deleteApplicationCacheFilesLI(packageName, userId);
11376 clearExternalStorageDataSync(packageName, userId, false);
11377 if(observer != null) {
11379 observer.onRemoveCompleted(packageName, succeded);
11380 } catch (RemoteException e) {
11381 Log.i(TAG, "Observer no longer exists.");
11383 } //end if observer
11388 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
11389 if (packageName == null) {
11390 Slog.w(TAG, "Attempt to delete null packageName.");
11393 PackageParser.Package p;
11394 synchronized (mPackages) {
11395 p = mPackages.get(packageName);
11398 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
11401 final ApplicationInfo applicationInfo = p.applicationInfo;
11402 if (applicationInfo == null) {
11403 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
11406 int retCode = mInstaller.deleteCacheFiles(packageName, userId);
11408 Slog.w(TAG, "Couldn't remove cache files for package: "
11409 + packageName + " u" + userId);
11416 public void getPackageSizeInfo(final String packageName, int userHandle,
11417 final IPackageStatsObserver observer) {
11418 mContext.enforceCallingOrSelfPermission(
11419 android.Manifest.permission.GET_PACKAGE_SIZE, null);
11420 if (packageName == null) {
11421 throw new IllegalArgumentException("Attempt to get size of null packageName");
11424 PackageStats stats = new PackageStats(packageName, userHandle);
11427 * Queue up an async operation since the package measurement may take a
11430 Message msg = mHandler.obtainMessage(INIT_COPY);
11431 msg.obj = new MeasureParams(stats, observer);
11432 mHandler.sendMessage(msg);
11435 private boolean getPackageSizeInfoLI(String packageName, int userHandle,
11436 PackageStats pStats) {
11437 if (packageName == null) {
11438 Slog.w(TAG, "Attempt to get size of null packageName.");
11441 PackageParser.Package p;
11442 boolean dataOnly = false;
11443 String libDirRoot = null;
11444 String asecPath = null;
11445 PackageSetting ps = null;
11446 synchronized (mPackages) {
11447 p = mPackages.get(packageName);
11448 ps = mSettings.mPackages.get(packageName);
11451 if((ps == null) || (ps.pkg == null)) {
11452 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
11458 libDirRoot = ps.legacyNativeLibraryPathString;
11460 if (p != null && (isExternal(p) || isForwardLocked(p))) {
11461 String secureContainerId = cidFromCodePath(p.applicationInfo.getBaseCodePath());
11462 if (secureContainerId != null) {
11463 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
11467 String publicSrcDir = null;
11469 final ApplicationInfo applicationInfo = p.applicationInfo;
11470 if (applicationInfo == null) {
11471 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
11474 if (isForwardLocked(p)) {
11475 publicSrcDir = applicationInfo.getBaseResourcePath();
11478 // TODO: extend to measure size of split APKs
11479 // TODO(multiArch): Extend getSizeInfo to look at the full subdirectory tree,
11480 // not just the first level.
11481 // TODO(multiArch): Extend getSizeInfo to look at *all* instruction sets, not
11482 // just the primary.
11483 String[] dexCodeInstructionSets = getDexCodeInstructionSets(getAppDexInstructionSets(ps));
11484 int res = mInstaller.getSizeInfo(packageName, userHandle, p.baseCodePath, libDirRoot,
11485 publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
11490 // Fix-up for forward-locked applications in ASEC containers.
11491 if (!isExternal(p)) {
11492 pStats.codeSize += pStats.externalCodeSize;
11493 pStats.externalCodeSize = 0L;
11501 public void addPackageToPreferred(String packageName) {
11502 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
11506 public void removePackageFromPreferred(String packageName) {
11507 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
11511 public List<PackageInfo> getPreferredPackages(int flags) {
11512 return new ArrayList<PackageInfo>();
11515 private int getUidTargetSdkVersionLockedLPr(int uid) {
11516 Object obj = mSettings.getUserIdLPr(uid);
11517 if (obj instanceof SharedUserSetting) {
11518 final SharedUserSetting sus = (SharedUserSetting) obj;
11519 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
11520 final Iterator<PackageSetting> it = sus.packages.iterator();
11521 while (it.hasNext()) {
11522 final PackageSetting ps = it.next();
11523 if (ps.pkg != null) {
11524 int v = ps.pkg.applicationInfo.targetSdkVersion;
11525 if (v < vers) vers = v;
11529 } else if (obj instanceof PackageSetting) {
11530 final PackageSetting ps = (PackageSetting) obj;
11531 if (ps.pkg != null) {
11532 return ps.pkg.applicationInfo.targetSdkVersion;
11535 return Build.VERSION_CODES.CUR_DEVELOPMENT;
11539 public void addPreferredActivity(IntentFilter filter, int match,
11540 ComponentName[] set, ComponentName activity, int userId) {
11541 addPreferredActivityInternal(filter, match, set, activity, true, userId,
11542 "Adding preferred");
11545 private void addPreferredActivityInternal(IntentFilter filter, int match,
11546 ComponentName[] set, ComponentName activity, boolean always, int userId,
11549 int callingUid = Binder.getCallingUid();
11550 enforceCrossUserPermission(callingUid, userId, true, false, "add preferred activity");
11551 if (filter.countActions() == 0) {
11552 Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
11555 synchronized (mPackages) {
11556 if (mContext.checkCallingOrSelfPermission(
11557 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
11558 != PackageManager.PERMISSION_GRANTED) {
11559 if (getUidTargetSdkVersionLockedLPr(callingUid)
11560 < Build.VERSION_CODES.FROYO) {
11561 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
11565 mContext.enforceCallingOrSelfPermission(
11566 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
11569 PreferredIntentResolver pir = mSettings.editPreferredActivitiesLPw(userId);
11570 Slog.i(TAG, opname + " activity " + activity.flattenToShortString() + " for user "
11572 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
11573 pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
11574 scheduleWritePackageRestrictionsLocked(userId);
11579 public void replacePreferredActivity(IntentFilter filter, int match,
11580 ComponentName[] set, ComponentName activity, int userId) {
11581 if (filter.countActions() != 1) {
11582 throw new IllegalArgumentException(
11583 "replacePreferredActivity expects filter to have only 1 action.");
11585 if (filter.countDataAuthorities() != 0
11586 || filter.countDataPaths() != 0
11587 || filter.countDataSchemes() > 1
11588 || filter.countDataTypes() != 0) {
11589 throw new IllegalArgumentException(
11590 "replacePreferredActivity expects filter to have no data authorities, " +
11591 "paths, or types; and at most one scheme.");
11594 final int callingUid = Binder.getCallingUid();
11595 enforceCrossUserPermission(callingUid, userId, true, false, "replace preferred activity");
11596 synchronized (mPackages) {
11597 if (mContext.checkCallingOrSelfPermission(
11598 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
11599 != PackageManager.PERMISSION_GRANTED) {
11600 if (getUidTargetSdkVersionLockedLPr(callingUid)
11601 < Build.VERSION_CODES.FROYO) {
11602 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
11603 + Binder.getCallingUid());
11606 mContext.enforceCallingOrSelfPermission(
11607 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
11610 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
11612 // Get all of the existing entries that exactly match this filter.
11613 ArrayList<PreferredActivity> existing = pir.findFilters(filter);
11614 if (existing != null && existing.size() == 1) {
11615 PreferredActivity cur = existing.get(0);
11616 if (DEBUG_PREFERRED) {
11617 Slog.i(TAG, "Checking replace of preferred:");
11618 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
11619 if (!cur.mPref.mAlways) {
11620 Slog.i(TAG, " -- CUR; not mAlways!");
11622 Slog.i(TAG, " -- CUR: mMatch=" + cur.mPref.mMatch);
11623 Slog.i(TAG, " -- CUR: mSet="
11624 + Arrays.toString(cur.mPref.mSetComponents));
11625 Slog.i(TAG, " -- CUR: mComponent=" + cur.mPref.mShortComponent);
11626 Slog.i(TAG, " -- NEW: mMatch="
11627 + (match&IntentFilter.MATCH_CATEGORY_MASK));
11628 Slog.i(TAG, " -- CUR: mSet=" + Arrays.toString(set));
11629 Slog.i(TAG, " -- CUR: mComponent=" + activity.flattenToShortString());
11632 if (cur.mPref.mAlways && cur.mPref.mComponent.equals(activity)
11633 && cur.mPref.mMatch == (match&IntentFilter.MATCH_CATEGORY_MASK)
11634 && cur.mPref.sameSet(set)) {
11635 // Setting the preferred activity to what it happens to be already
11636 if (DEBUG_PREFERRED) {
11637 Slog.i(TAG, "Replacing with same preferred activity "
11638 + cur.mPref.mShortComponent + " for user "
11640 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
11646 if (existing != null) {
11647 if (DEBUG_PREFERRED) {
11648 Slog.i(TAG, existing.size() + " existing preferred matches for:");
11649 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
11651 for (int i = 0; i < existing.size(); i++) {
11652 PreferredActivity pa = existing.get(i);
11653 if (DEBUG_PREFERRED) {
11654 Slog.i(TAG, "Removing existing preferred activity "
11655 + pa.mPref.mComponent + ":");
11656 pa.dump(new LogPrinter(Log.INFO, TAG), " ");
11658 pir.removeFilter(pa);
11662 addPreferredActivityInternal(filter, match, set, activity, true, userId,
11663 "Replacing preferred");
11668 public void clearPackagePreferredActivities(String packageName) {
11669 final int uid = Binder.getCallingUid();
11671 synchronized (mPackages) {
11672 PackageParser.Package pkg = mPackages.get(packageName);
11673 if (pkg == null || pkg.applicationInfo.uid != uid) {
11674 if (mContext.checkCallingOrSelfPermission(
11675 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
11676 != PackageManager.PERMISSION_GRANTED) {
11677 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
11678 < Build.VERSION_CODES.FROYO) {
11679 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
11680 + Binder.getCallingUid());
11683 mContext.enforceCallingOrSelfPermission(
11684 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
11688 int user = UserHandle.getCallingUserId();
11689 if (clearPackagePreferredActivitiesLPw(packageName, user)) {
11690 scheduleWritePackageRestrictionsLocked(user);
11695 /** This method takes a specific user id as well as UserHandle.USER_ALL. */
11696 boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
11697 ArrayList<PreferredActivity> removed = null;
11698 boolean changed = false;
11699 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
11700 final int thisUserId = mSettings.mPreferredActivities.keyAt(i);
11701 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
11702 if (userId != UserHandle.USER_ALL && userId != thisUserId) {
11705 Iterator<PreferredActivity> it = pir.filterIterator();
11706 while (it.hasNext()) {
11707 PreferredActivity pa = it.next();
11708 // Mark entry for removal only if it matches the package name
11709 // and the entry is of type "always".
11710 if (packageName == null ||
11711 (pa.mPref.mComponent.getPackageName().equals(packageName)
11712 && pa.mPref.mAlways)) {
11713 if (removed == null) {
11714 removed = new ArrayList<PreferredActivity>();
11719 if (removed != null) {
11720 for (int j=0; j<removed.size(); j++) {
11721 PreferredActivity pa = removed.get(j);
11722 pir.removeFilter(pa);
11731 public void resetPreferredActivities(int userId) {
11732 /* TODO: Actually use userId. Why is it being passed in? */
11733 mContext.enforceCallingOrSelfPermission(
11734 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
11736 synchronized (mPackages) {
11737 int user = UserHandle.getCallingUserId();
11738 clearPackagePreferredActivitiesLPw(null, user);
11739 mSettings.readDefaultPreferredAppsLPw(this, user);
11740 scheduleWritePackageRestrictionsLocked(user);
11745 public int getPreferredActivities(List<IntentFilter> outFilters,
11746 List<ComponentName> outActivities, String packageName) {
11749 final int userId = UserHandle.getCallingUserId();
11751 synchronized (mPackages) {
11752 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
11754 final Iterator<PreferredActivity> it = pir.filterIterator();
11755 while (it.hasNext()) {
11756 final PreferredActivity pa = it.next();
11757 if (packageName == null
11758 || (pa.mPref.mComponent.getPackageName().equals(packageName)
11759 && pa.mPref.mAlways)) {
11760 if (outFilters != null) {
11761 outFilters.add(new IntentFilter(pa));
11763 if (outActivities != null) {
11764 outActivities.add(pa.mPref.mComponent);
11775 public void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity,
11777 int callingUid = Binder.getCallingUid();
11778 if (callingUid != Process.SYSTEM_UID) {
11779 throw new SecurityException(
11780 "addPersistentPreferredActivity can only be run by the system");
11782 if (filter.countActions() == 0) {
11783 Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
11786 synchronized (mPackages) {
11787 Slog.i(TAG, "Adding persistent preferred activity " + activity + " for user " + userId +
11789 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
11790 mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
11791 new PersistentPreferredActivity(filter, activity));
11792 scheduleWritePackageRestrictionsLocked(userId);
11797 public void clearPackagePersistentPreferredActivities(String packageName, int userId) {
11798 int callingUid = Binder.getCallingUid();
11799 if (callingUid != Process.SYSTEM_UID) {
11800 throw new SecurityException(
11801 "clearPackagePersistentPreferredActivities can only be run by the system");
11803 ArrayList<PersistentPreferredActivity> removed = null;
11804 boolean changed = false;
11805 synchronized (mPackages) {
11806 for (int i=0; i<mSettings.mPersistentPreferredActivities.size(); i++) {
11807 final int thisUserId = mSettings.mPersistentPreferredActivities.keyAt(i);
11808 PersistentPreferredIntentResolver ppir = mSettings.mPersistentPreferredActivities
11810 if (userId != thisUserId) {
11813 Iterator<PersistentPreferredActivity> it = ppir.filterIterator();
11814 while (it.hasNext()) {
11815 PersistentPreferredActivity ppa = it.next();
11816 // Mark entry for removal only if it matches the package name.
11817 if (ppa.mComponent.getPackageName().equals(packageName)) {
11818 if (removed == null) {
11819 removed = new ArrayList<PersistentPreferredActivity>();
11824 if (removed != null) {
11825 for (int j=0; j<removed.size(); j++) {
11826 PersistentPreferredActivity ppa = removed.get(j);
11827 ppir.removeFilter(ppa);
11834 scheduleWritePackageRestrictionsLocked(userId);
11840 public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage,
11841 int ownerUserId, int sourceUserId, int targetUserId, int flags) {
11842 mContext.enforceCallingOrSelfPermission(
11843 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
11844 int callingUid = Binder.getCallingUid();
11845 enforceOwnerRights(ownerPackage, ownerUserId, callingUid);
11846 enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
11847 if (intentFilter.countActions() == 0) {
11848 Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions");
11851 synchronized (mPackages) {
11852 CrossProfileIntentFilter newFilter = new CrossProfileIntentFilter(intentFilter,
11853 ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags);
11854 CrossProfileIntentResolver resolver =
11855 mSettings.editCrossProfileIntentResolverLPw(sourceUserId);
11856 ArrayList<CrossProfileIntentFilter> existing = resolver.findFilters(intentFilter);
11857 // We have all those whose filter is equal. Now checking if the rest is equal as well.
11858 if (existing != null) {
11859 int size = existing.size();
11860 for (int i = 0; i < size; i++) {
11861 if (newFilter.equalsIgnoreFilter(existing.get(i))) {
11866 resolver.addFilter(newFilter);
11867 scheduleWritePackageRestrictionsLocked(sourceUserId);
11872 public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage,
11874 mContext.enforceCallingOrSelfPermission(
11875 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
11876 int callingUid = Binder.getCallingUid();
11877 enforceOwnerRights(ownerPackage, ownerUserId, callingUid);
11878 enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
11879 int callingUserId = UserHandle.getUserId(callingUid);
11880 synchronized (mPackages) {
11881 CrossProfileIntentResolver resolver =
11882 mSettings.editCrossProfileIntentResolverLPw(sourceUserId);
11883 ArraySet<CrossProfileIntentFilter> set =
11884 new ArraySet<CrossProfileIntentFilter>(resolver.filterSet());
11885 for (CrossProfileIntentFilter filter : set) {
11886 if (filter.getOwnerPackage().equals(ownerPackage)
11887 && filter.getOwnerUserId() == callingUserId) {
11888 resolver.removeFilter(filter);
11891 scheduleWritePackageRestrictionsLocked(sourceUserId);
11895 // Enforcing that callingUid is owning pkg on userId
11896 private void enforceOwnerRights(String pkg, int userId, int callingUid) {
11897 // The system owns everything.
11898 if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
11901 int callingUserId = UserHandle.getUserId(callingUid);
11902 if (callingUserId != userId) {
11903 throw new SecurityException("calling uid " + callingUid
11904 + " pretends to own " + pkg + " on user " + userId + " but belongs to user "
11907 PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
11909 throw new IllegalArgumentException("Unknown package " + pkg + " on user "
11912 if (!UserHandle.isSameApp(pi.applicationInfo.uid, callingUid)) {
11913 throw new SecurityException("Calling uid " + callingUid
11914 + " does not own package " + pkg);
11919 public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
11920 Intent intent = new Intent(Intent.ACTION_MAIN);
11921 intent.addCategory(Intent.CATEGORY_HOME);
11923 final int callingUserId = UserHandle.getCallingUserId();
11924 List<ResolveInfo> list = queryIntentActivities(intent, null,
11925 PackageManager.GET_META_DATA, callingUserId);
11926 ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
11927 true, false, false, callingUserId);
11929 allHomeCandidates.clear();
11930 if (list != null) {
11931 for (ResolveInfo ri : list) {
11932 allHomeCandidates.add(ri);
11935 return (preferred == null || preferred.activityInfo == null)
11937 : new ComponentName(preferred.activityInfo.packageName,
11938 preferred.activityInfo.name);
11942 public void setApplicationEnabledSetting(String appPackageName,
11943 int newState, int flags, int userId, String callingPackage) {
11944 if (!sUserManager.exists(userId)) return;
11945 if (callingPackage == null) {
11946 callingPackage = Integer.toString(Binder.getCallingUid());
11948 setEnabledSetting(appPackageName, null, newState, flags, userId, callingPackage);
11952 public void setComponentEnabledSetting(ComponentName componentName,
11953 int newState, int flags, int userId) {
11954 if (!sUserManager.exists(userId)) return;
11955 setEnabledSetting(componentName.getPackageName(),
11956 componentName.getClassName(), newState, flags, userId, null);
11959 private void setEnabledSetting(final String packageName, String className, int newState,
11960 final int flags, int userId, String callingPackage) {
11961 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
11962 || newState == COMPONENT_ENABLED_STATE_ENABLED
11963 || newState == COMPONENT_ENABLED_STATE_DISABLED
11964 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER
11965 || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
11966 throw new IllegalArgumentException("Invalid new component state: "
11969 PackageSetting pkgSetting;
11970 final int uid = Binder.getCallingUid();
11971 final int permission = mContext.checkCallingOrSelfPermission(
11972 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
11973 enforceCrossUserPermission(uid, userId, false, true, "set enabled");
11974 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
11975 boolean sendNow = false;
11976 boolean isApp = (className == null);
11977 String componentName = isApp ? packageName : className;
11978 int packageUid = -1;
11979 ArrayList<String> components;
11982 synchronized (mPackages) {
11983 pkgSetting = mSettings.mPackages.get(packageName);
11984 if (pkgSetting == null) {
11985 if (className == null) {
11986 throw new IllegalArgumentException(
11987 "Unknown package: " + packageName);
11989 throw new IllegalArgumentException(
11990 "Unknown component: " + packageName
11991 + "/" + className);
11993 // Allow root and verify that userId is not being specified by a different user
11994 if (!allowedByPermission && !UserHandle.isSameApp(uid, pkgSetting.appId)) {
11995 throw new SecurityException(
11996 "Permission Denial: attempt to change component state from pid="
11997 + Binder.getCallingPid()
11998 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
12000 if (className == null) {
12001 // We're dealing with an application/package level state change
12002 if (pkgSetting.getEnabled(userId) == newState) {
12006 if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
12007 || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
12008 // Don't care about who enables an app.
12009 callingPackage = null;
12011 pkgSetting.setEnabled(newState, userId, callingPackage);
12012 // pkgSetting.pkg.mSetEnabled = newState;
12014 // We're dealing with a component level state change
12015 // First, verify that this is a valid class name.
12016 PackageParser.Package pkg = pkgSetting.pkg;
12017 if (pkg == null || !pkg.hasComponentClassName(className)) {
12018 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
12019 throw new IllegalArgumentException("Component class " + className
12020 + " does not exist in " + packageName);
12022 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
12023 + className + " does not exist in " + packageName);
12026 switch (newState) {
12027 case COMPONENT_ENABLED_STATE_ENABLED:
12028 if (!pkgSetting.enableComponentLPw(className, userId)) {
12032 case COMPONENT_ENABLED_STATE_DISABLED:
12033 if (!pkgSetting.disableComponentLPw(className, userId)) {
12037 case COMPONENT_ENABLED_STATE_DEFAULT:
12038 if (!pkgSetting.restoreComponentLPw(className, userId)) {
12043 Slog.e(TAG, "Invalid new component state: " + newState);
12047 mSettings.writePackageRestrictionsLPr(userId);
12048 components = mPendingBroadcasts.get(userId, packageName);
12049 final boolean newPackage = components == null;
12051 components = new ArrayList<String>();
12053 if (!components.contains(componentName)) {
12054 components.add(componentName);
12056 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
12058 // Purge entry from pending broadcast list if another one exists already
12059 // since we are sending one right away.
12060 mPendingBroadcasts.remove(userId, packageName);
12063 mPendingBroadcasts.put(userId, packageName, components);
12065 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
12066 // Schedule a message
12067 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
12072 long callingId = Binder.clearCallingIdentity();
12075 packageUid = UserHandle.getUid(userId, pkgSetting.appId);
12076 sendPackageChangedBroadcast(packageName,
12077 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
12080 Binder.restoreCallingIdentity(callingId);
12084 private void sendPackageChangedBroadcast(String packageName,
12085 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
12087 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
12089 Bundle extras = new Bundle(4);
12090 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
12091 String nameList[] = new String[componentNames.size()];
12092 componentNames.toArray(nameList);
12093 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
12094 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
12095 extras.putInt(Intent.EXTRA_UID, packageUid);
12096 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
12097 new int[] {UserHandle.getUserId(packageUid)});
12101 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
12102 if (!sUserManager.exists(userId)) return;
12103 final int uid = Binder.getCallingUid();
12104 final int permission = mContext.checkCallingOrSelfPermission(
12105 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
12106 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
12107 enforceCrossUserPermission(uid, userId, true, true, "stop package");
12109 synchronized (mPackages) {
12110 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
12112 scheduleWritePackageRestrictionsLocked(userId);
12118 public String getInstallerPackageName(String packageName) {
12120 synchronized (mPackages) {
12121 return mSettings.getInstallerPackageNameLPr(packageName);
12126 public int getApplicationEnabledSetting(String packageName, int userId) {
12127 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
12128 int uid = Binder.getCallingUid();
12129 enforceCrossUserPermission(uid, userId, false, false, "get enabled");
12131 synchronized (mPackages) {
12132 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
12137 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
12138 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
12139 int uid = Binder.getCallingUid();
12140 enforceCrossUserPermission(uid, userId, false, false, "get component enabled");
12142 synchronized (mPackages) {
12143 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
12148 public void enterSafeMode() {
12149 enforceSystemOrRoot("Only the system can request entering safe mode");
12151 if (!mSystemReady) {
12157 public void systemReady() {
12158 mSystemReady = true;
12160 // Read the compatibilty setting when the system is ready.
12161 boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
12162 mContext.getContentResolver(),
12163 android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
12164 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
12165 if (DEBUG_SETTINGS) {
12166 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
12169 synchronized (mPackages) {
12170 // Verify that all of the preferred activity components actually
12171 // exist. It is possible for applications to be updated and at
12172 // that point remove a previously declared activity component that
12173 // had been set as a preferred activity. We try to clean this up
12174 // the next time we encounter that preferred activity, but it is
12175 // possible for the user flow to never be able to return to that
12176 // situation so here we do a sanity check to make sure we haven't
12177 // left any junk around.
12178 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
12179 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
12180 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
12182 for (PreferredActivity pa : pir.filterSet()) {
12183 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
12187 if (removed.size() > 0) {
12188 for (int r=0; r<removed.size(); r++) {
12189 PreferredActivity pa = removed.get(r);
12190 Slog.w(TAG, "Removing dangling preferred activity: "
12191 + pa.mPref.mComponent);
12192 pir.removeFilter(pa);
12194 mSettings.writePackageRestrictionsLPr(
12195 mSettings.mPreferredActivities.keyAt(i));
12199 sUserManager.systemReady();
12201 // Kick off any messages waiting for system ready
12202 if (mPostSystemReadyMessages != null) {
12203 for (Message msg : mPostSystemReadyMessages) {
12204 msg.sendToTarget();
12206 mPostSystemReadyMessages = null;
12211 public boolean isSafeMode() {
12216 public boolean hasSystemUidErrors() {
12217 return mHasSystemUidErrors;
12220 static String arrayToString(int[] array) {
12221 StringBuffer buf = new StringBuffer(128);
12223 if (array != null) {
12224 for (int i=0; i<array.length; i++) {
12225 if (i > 0) buf.append(", ");
12226 buf.append(array[i]);
12230 return buf.toString();
12233 static class DumpState {
12234 public static final int DUMP_LIBS = 1 << 0;
12235 public static final int DUMP_FEATURES = 1 << 1;
12236 public static final int DUMP_RESOLVERS = 1 << 2;
12237 public static final int DUMP_PERMISSIONS = 1 << 3;
12238 public static final int DUMP_PACKAGES = 1 << 4;
12239 public static final int DUMP_SHARED_USERS = 1 << 5;
12240 public static final int DUMP_MESSAGES = 1 << 6;
12241 public static final int DUMP_PROVIDERS = 1 << 7;
12242 public static final int DUMP_VERIFIERS = 1 << 8;
12243 public static final int DUMP_PREFERRED = 1 << 9;
12244 public static final int DUMP_PREFERRED_XML = 1 << 10;
12245 public static final int DUMP_KEYSETS = 1 << 11;
12246 public static final int DUMP_VERSION = 1 << 12;
12247 public static final int DUMP_INSTALLS = 1 << 13;
12249 public static final int OPTION_SHOW_FILTERS = 1 << 0;
12251 private int mTypes;
12253 private int mOptions;
12255 private boolean mTitlePrinted;
12257 private SharedUserSetting mSharedUser;
12259 public boolean isDumping(int type) {
12260 if (mTypes == 0 && type != DUMP_PREFERRED_XML) {
12264 return (mTypes & type) != 0;
12267 public void setDump(int type) {
12271 public boolean isOptionEnabled(int option) {
12272 return (mOptions & option) != 0;
12275 public void setOptionEnabled(int option) {
12276 mOptions |= option;
12279 public boolean onTitlePrinted() {
12280 final boolean printed = mTitlePrinted;
12281 mTitlePrinted = true;
12285 public boolean getTitlePrinted() {
12286 return mTitlePrinted;
12289 public void setTitlePrinted(boolean enabled) {
12290 mTitlePrinted = enabled;
12293 public SharedUserSetting getSharedUser() {
12294 return mSharedUser;
12297 public void setSharedUser(SharedUserSetting user) {
12298 mSharedUser = user;
12303 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
12304 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
12305 != PackageManager.PERMISSION_GRANTED) {
12306 pw.println("Permission Denial: can't dump ActivityManager from from pid="
12307 + Binder.getCallingPid()
12308 + ", uid=" + Binder.getCallingUid()
12309 + " without permission "
12310 + android.Manifest.permission.DUMP);
12314 DumpState dumpState = new DumpState();
12315 boolean fullPreferred = false;
12316 boolean checkin = false;
12318 String packageName = null;
12321 while (opti < args.length) {
12322 String opt = args[opti];
12323 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
12328 if ("-a".equals(opt)) {
12329 // Right now we only know how to print all.
12330 } else if ("-h".equals(opt)) {
12331 pw.println("Package manager dump options:");
12332 pw.println(" [-h] [-f] [--checkin] [cmd] ...");
12333 pw.println(" --checkin: dump for a checkin");
12334 pw.println(" -f: print details of intent filters");
12335 pw.println(" -h: print this help");
12336 pw.println(" cmd may be one of:");
12337 pw.println(" l[ibraries]: list known shared libraries");
12338 pw.println(" f[ibraries]: list device features");
12339 pw.println(" k[eysets]: print known keysets");
12340 pw.println(" r[esolvers]: dump intent resolvers");
12341 pw.println(" perm[issions]: dump permissions");
12342 pw.println(" pref[erred]: print preferred package settings");
12343 pw.println(" preferred-xml [--full]: print preferred package settings as xml");
12344 pw.println(" prov[iders]: dump content providers");
12345 pw.println(" p[ackages]: dump installed packages");
12346 pw.println(" s[hared-users]: dump shared user IDs");
12347 pw.println(" m[essages]: print collected runtime messages");
12348 pw.println(" v[erifiers]: print package verifier info");
12349 pw.println(" version: print database version info");
12350 pw.println(" write: write current settings now");
12351 pw.println(" <package.name>: info about given package");
12352 pw.println(" installs: details about install sessions");
12354 } else if ("--checkin".equals(opt)) {
12356 } else if ("-f".equals(opt)) {
12357 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
12359 pw.println("Unknown argument: " + opt + "; use -h for help");
12363 // Is the caller requesting to dump a particular piece of data?
12364 if (opti < args.length) {
12365 String cmd = args[opti];
12367 // Is this a package name?
12368 if ("android".equals(cmd) || cmd.contains(".")) {
12370 // When dumping a single package, we always dump all of its
12371 // filter information since the amount of data will be reasonable.
12372 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
12373 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
12374 dumpState.setDump(DumpState.DUMP_LIBS);
12375 } else if ("f".equals(cmd) || "features".equals(cmd)) {
12376 dumpState.setDump(DumpState.DUMP_FEATURES);
12377 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
12378 dumpState.setDump(DumpState.DUMP_RESOLVERS);
12379 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
12380 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
12381 } else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
12382 dumpState.setDump(DumpState.DUMP_PREFERRED);
12383 } else if ("preferred-xml".equals(cmd)) {
12384 dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
12385 if (opti < args.length && "--full".equals(args[opti])) {
12386 fullPreferred = true;
12389 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
12390 dumpState.setDump(DumpState.DUMP_PACKAGES);
12391 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
12392 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
12393 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
12394 dumpState.setDump(DumpState.DUMP_PROVIDERS);
12395 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
12396 dumpState.setDump(DumpState.DUMP_MESSAGES);
12397 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
12398 dumpState.setDump(DumpState.DUMP_VERIFIERS);
12399 } else if ("version".equals(cmd)) {
12400 dumpState.setDump(DumpState.DUMP_VERSION);
12401 } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
12402 dumpState.setDump(DumpState.DUMP_KEYSETS);
12403 } else if ("installs".equals(cmd)) {
12404 dumpState.setDump(DumpState.DUMP_INSTALLS);
12405 } else if ("write".equals(cmd)) {
12406 synchronized (mPackages) {
12407 mSettings.writeLPr();
12408 pw.println("Settings written.");
12415 pw.println("vers,1");
12419 synchronized (mPackages) {
12420 if (dumpState.isDumping(DumpState.DUMP_VERSION) && packageName == null) {
12422 if (dumpState.onTitlePrinted())
12424 pw.println("Database versions:");
12425 pw.print(" SDK Version:");
12426 pw.print(" internal=");
12427 pw.print(mSettings.mInternalSdkPlatform);
12428 pw.print(" external=");
12429 pw.println(mSettings.mExternalSdkPlatform);
12430 pw.print(" DB Version:");
12431 pw.print(" internal=");
12432 pw.print(mSettings.mInternalDatabaseVersion);
12433 pw.print(" external=");
12434 pw.println(mSettings.mExternalDatabaseVersion);
12438 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
12440 if (dumpState.onTitlePrinted())
12442 pw.println("Verifiers:");
12443 pw.print(" Required: ");
12444 pw.print(mRequiredVerifierPackage);
12445 pw.print(" (uid=");
12446 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
12448 } else if (mRequiredVerifierPackage != null) {
12449 pw.print("vrfy,"); pw.print(mRequiredVerifierPackage);
12450 pw.print(","); pw.println(getPackageUid(mRequiredVerifierPackage, 0));
12454 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
12455 boolean printedHeader = false;
12456 final Iterator<String> it = mSharedLibraries.keySet().iterator();
12457 while (it.hasNext()) {
12458 String name = it.next();
12459 SharedLibraryEntry ent = mSharedLibraries.get(name);
12461 if (!printedHeader) {
12462 if (dumpState.onTitlePrinted())
12464 pw.println("Libraries:");
12465 printedHeader = true;
12475 if (ent.path != null) {
12477 pw.print("(jar) ");
12478 pw.print(ent.path);
12481 pw.print(ent.path);
12485 pw.print("(apk) ");
12496 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
12497 if (dumpState.onTitlePrinted())
12500 pw.println("Features:");
12502 Iterator<String> it = mAvailableFeatures.keySet().iterator();
12503 while (it.hasNext()) {
12504 String name = it.next();
12514 if (!checkin && dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
12515 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
12516 : "Activity Resolver Table:", " ", packageName,
12517 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
12518 dumpState.setTitlePrinted(true);
12520 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
12521 : "Receiver Resolver Table:", " ", packageName,
12522 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
12523 dumpState.setTitlePrinted(true);
12525 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
12526 : "Service Resolver Table:", " ", packageName,
12527 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
12528 dumpState.setTitlePrinted(true);
12530 if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
12531 : "Provider Resolver Table:", " ", packageName,
12532 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
12533 dumpState.setTitlePrinted(true);
12537 if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
12538 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
12539 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
12540 int user = mSettings.mPreferredActivities.keyAt(i);
12542 dumpState.getTitlePrinted()
12543 ? "\nPreferred Activities User " + user + ":"
12544 : "Preferred Activities User " + user + ":", " ",
12545 packageName, true)) {
12546 dumpState.setTitlePrinted(true);
12551 if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
12553 FileOutputStream fout = new FileOutputStream(fd);
12554 BufferedOutputStream str = new BufferedOutputStream(fout);
12555 XmlSerializer serializer = new FastXmlSerializer();
12557 serializer.setOutput(str, "utf-8");
12558 serializer.startDocument(null, true);
12559 serializer.setFeature(
12560 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
12561 mSettings.writePreferredActivitiesLPr(serializer, 0, fullPreferred);
12562 serializer.endDocument();
12563 serializer.flush();
12564 } catch (IllegalArgumentException e) {
12565 pw.println("Failed writing: " + e);
12566 } catch (IllegalStateException e) {
12567 pw.println("Failed writing: " + e);
12568 } catch (IOException e) {
12569 pw.println("Failed writing: " + e);
12573 if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
12574 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
12575 if (packageName == null) {
12576 for (int iperm=0; iperm<mAppOpPermissionPackages.size(); iperm++) {
12578 if (dumpState.onTitlePrinted())
12580 pw.println("AppOp Permissions:");
12582 pw.print(" AppOp Permission ");
12583 pw.print(mAppOpPermissionPackages.keyAt(iperm));
12585 ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
12586 for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
12587 pw.print(" "); pw.println(pkgs.valueAt(ipkg));
12593 if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
12594 boolean printedSomething = false;
12595 for (PackageParser.Provider p : mProviders.mProviders.values()) {
12596 if (packageName != null && !packageName.equals(p.info.packageName)) {
12599 if (!printedSomething) {
12600 if (dumpState.onTitlePrinted())
12602 pw.println("Registered ContentProviders:");
12603 printedSomething = true;
12605 pw.print(" "); p.printComponentShortName(pw); pw.println(":");
12606 pw.print(" "); pw.println(p.toString());
12608 printedSomething = false;
12609 for (Map.Entry<String, PackageParser.Provider> entry :
12610 mProvidersByAuthority.entrySet()) {
12611 PackageParser.Provider p = entry.getValue();
12612 if (packageName != null && !packageName.equals(p.info.packageName)) {
12615 if (!printedSomething) {
12616 if (dumpState.onTitlePrinted())
12618 pw.println("ContentProvider Authorities:");
12619 printedSomething = true;
12621 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
12622 pw.print(" "); pw.println(p.toString());
12623 if (p.info != null && p.info.applicationInfo != null) {
12624 final String appInfo = p.info.applicationInfo.toString();
12625 pw.print(" applicationInfo="); pw.println(appInfo);
12630 if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
12631 mSettings.mKeySetManagerService.dumpLPr(pw, packageName, dumpState);
12634 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
12635 mSettings.dumpPackagesLPr(pw, packageName, dumpState, checkin);
12638 if (!checkin && dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
12639 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
12642 if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) {
12643 // XXX should handle packageName != null by dumping only install data that
12644 // the given package is involved with.
12645 if (dumpState.onTitlePrinted()) pw.println();
12646 mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
12649 if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
12650 if (dumpState.onTitlePrinted()) pw.println();
12651 mSettings.dumpReadMessagesLPr(pw, dumpState);
12654 pw.println("Package warning messages:");
12655 final File fname = getSettingsProblemFile();
12656 FileInputStream in = null;
12658 in = new FileInputStream(fname);
12659 final int avail = in.available();
12660 final byte[] data = new byte[avail];
12662 pw.print(new String(data));
12663 } catch (FileNotFoundException e) {
12664 } catch (IOException e) {
12669 } catch (IOException e) {
12675 if (checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES)) {
12676 BufferedReader in = null;
12677 String line = null;
12679 in = new BufferedReader(new FileReader(getSettingsProblemFile()));
12680 while ((line = in.readLine()) != null) {
12684 } catch (IOException ignored) {
12686 IoUtils.closeQuietly(in);
12692 // ------- apps on sdcard specific code -------
12693 static final boolean DEBUG_SD_INSTALL = false;
12695 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
12697 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
12699 private boolean mMediaMounted = false;
12701 static String getEncryptKey() {
12703 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
12704 SD_ENCRYPTION_KEYSTORE_NAME);
12705 if (sdEncKey == null) {
12706 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
12707 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
12708 if (sdEncKey == null) {
12709 Slog.e(TAG, "Failed to create encryption keys");
12714 } catch (NoSuchAlgorithmException nsae) {
12715 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
12717 } catch (IOException ioe) {
12718 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
12724 * Update media status on PackageManager.
12727 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
12728 int callingUid = Binder.getCallingUid();
12729 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
12730 throw new SecurityException("Media status can only be updated by the system");
12732 // reader; this apparently protects mMediaMounted, but should probably
12733 // be a different lock in that case.
12734 synchronized (mPackages) {
12735 Log.i(TAG, "Updating external media status from "
12736 + (mMediaMounted ? "mounted" : "unmounted") + " to "
12737 + (mediaStatus ? "mounted" : "unmounted"));
12738 if (DEBUG_SD_INSTALL)
12739 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
12740 + ", mMediaMounted=" + mMediaMounted);
12741 if (mediaStatus == mMediaMounted) {
12742 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
12744 mHandler.sendMessage(msg);
12747 mMediaMounted = mediaStatus;
12749 // Queue up an async operation since the package installation may take a
12751 mHandler.post(new Runnable() {
12752 public void run() {
12753 updateExternalMediaStatusInner(mediaStatus, reportStatus, true);
12759 * Called by MountService when the initial ASECs to scan are available.
12760 * Should block until all the ASEC containers are finished being scanned.
12762 public void scanAvailableAsecs() {
12763 updateExternalMediaStatusInner(true, false, false);
12764 if (mShouldRestoreconData) {
12765 SELinuxMMAC.setRestoreconDone();
12766 mShouldRestoreconData = false;
12771 * Collect information of applications on external media, map them against
12772 * existing containers and update information based on current mount status.
12773 * Please note that we always have to report status if reportStatus has been
12774 * set to true especially when unloading packages.
12776 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus,
12777 boolean externalStorage) {
12778 ArrayMap<AsecInstallArgs, String> processCids = new ArrayMap<>();
12779 int[] uidArr = EmptyArray.INT;
12781 final String[] list = PackageHelper.getSecureContainerList();
12782 if (ArrayUtils.isEmpty(list)) {
12783 Log.i(TAG, "No secure containers found");
12785 // Process list of secure containers and categorize them
12786 // as active or stale based on their package internal state.
12789 synchronized (mPackages) {
12790 for (String cid : list) {
12791 // Leave stages untouched for now; installer service owns them
12792 if (PackageInstallerService.isStageName(cid)) continue;
12794 if (DEBUG_SD_INSTALL)
12795 Log.i(TAG, "Processing container " + cid);
12796 String pkgName = getAsecPackageName(cid);
12797 if (pkgName == null) {
12798 Slog.i(TAG, "Found stale container " + cid + " with no package name");
12801 if (DEBUG_SD_INSTALL)
12802 Log.i(TAG, "Looking for pkg : " + pkgName);
12804 final PackageSetting ps = mSettings.mPackages.get(pkgName);
12806 Slog.i(TAG, "Found stale container " + cid + " with no matching settings");
12811 * Skip packages that are not external if we're unmounting
12812 * external storage.
12814 if (externalStorage && !isMounted && !isExternal(ps)) {
12818 final AsecInstallArgs args = new AsecInstallArgs(cid,
12819 getAppDexInstructionSets(ps), isForwardLocked(ps));
12820 // The package status is changed only if the code path
12821 // matches between settings and the container id.
12822 if (ps.codePathString != null
12823 && ps.codePathString.startsWith(args.getCodePath())) {
12824 if (DEBUG_SD_INSTALL) {
12825 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
12826 + " at code path: " + ps.codePathString);
12829 // We do have a valid package installed on sdcard
12830 processCids.put(args, ps.codePathString);
12831 final int uid = ps.appId;
12833 uidArr = ArrayUtils.appendInt(uidArr, uid);
12836 Slog.i(TAG, "Found stale container " + cid + ": expected codePath="
12837 + ps.codePathString);
12842 Arrays.sort(uidArr);
12845 // Process packages with valid entries.
12847 if (DEBUG_SD_INSTALL)
12848 Log.i(TAG, "Loading packages");
12849 loadMediaPackages(processCids, uidArr);
12850 startCleaningPackages();
12851 mInstallerService.onSecureContainersAvailable();
12853 if (DEBUG_SD_INSTALL)
12854 Log.i(TAG, "Unloading packages");
12855 unloadMediaPackages(processCids, uidArr, reportStatus);
12859 private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
12860 ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
12861 int size = pkgList.size();
12863 // Send broadcasts here
12864 Bundle extras = new Bundle();
12865 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
12866 .toArray(new String[size]));
12867 if (uidArr != null) {
12868 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
12871 extras.putBoolean(Intent.EXTRA_REPLACING, replacing);
12873 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
12874 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
12875 sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
12880 * Look at potentially valid container ids from processCids If package
12881 * information doesn't match the one on record or package scanning fails,
12882 * the cid is added to list of removeCids. We currently don't delete stale
12885 private void loadMediaPackages(ArrayMap<AsecInstallArgs, String> processCids, int[] uidArr) {
12886 ArrayList<String> pkgList = new ArrayList<String>();
12887 Set<AsecInstallArgs> keys = processCids.keySet();
12889 for (AsecInstallArgs args : keys) {
12890 String codePath = processCids.get(args);
12891 if (DEBUG_SD_INSTALL)
12892 Log.i(TAG, "Loading container : " + args.cid);
12893 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
12895 // Make sure there are no container errors first.
12896 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
12897 Slog.e(TAG, "Failed to mount cid : " + args.cid
12898 + " when installing from sdcard");
12901 // Check code path here.
12902 if (codePath == null || !codePath.startsWith(args.getCodePath())) {
12903 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
12904 + " does not match one in settings " + codePath);
12908 int parseFlags = mDefParseFlags;
12909 if (args.isExternal()) {
12910 parseFlags |= PackageParser.PARSE_ON_SDCARD;
12912 if (args.isFwdLocked()) {
12913 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
12916 synchronized (mInstallLock) {
12917 PackageParser.Package pkg = null;
12919 pkg = scanPackageLI(new File(codePath), parseFlags, 0, 0, null);
12920 } catch (PackageManagerException e) {
12921 Slog.w(TAG, "Failed to scan " + codePath + ": " + e.getMessage());
12923 // Scan the package
12926 * TODO why is the lock being held? doPostInstall is
12927 * called in other places without the lock. This needs
12928 * to be straightened out.
12931 synchronized (mPackages) {
12932 retCode = PackageManager.INSTALL_SUCCEEDED;
12933 pkgList.add(pkg.packageName);
12934 // Post process args
12935 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
12936 pkg.applicationInfo.uid);
12939 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
12944 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
12945 Log.w(TAG, "Container " + args.cid + " is stale, retCode=" + retCode);
12950 synchronized (mPackages) {
12951 // If the platform SDK has changed since the last time we booted,
12952 // we need to re-grant app permission to catch any new ones that
12953 // appear. This is really a hack, and means that apps can in some
12954 // cases get permissions that the user didn't initially explicitly
12955 // allow... it would be nice to have some better way to handle
12957 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
12958 if (regrantPermissions)
12959 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
12960 + mSdkVersion + "; regranting permissions for external storage");
12961 mSettings.mExternalSdkPlatform = mSdkVersion;
12963 // Make sure group IDs have been assigned, and any permission
12964 // changes in other apps are accounted for
12965 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
12966 | (regrantPermissions
12967 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
12970 mSettings.updateExternalDatabaseVersion();
12972 // can downgrade to reader
12973 // Persist settings
12974 mSettings.writeLPr();
12976 // Send a broadcast to let everyone know we are done processing
12977 if (pkgList.size() > 0) {
12978 sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null);
12983 * Utility method to unload a list of specified containers
12985 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
12986 // Just unmount all valid containers.
12987 for (AsecInstallArgs arg : cidArgs) {
12988 synchronized (mInstallLock) {
12989 arg.doPostDeleteLI(false);
12995 * Unload packages mounted on external media. This involves deleting package
12996 * data from internal structures, sending broadcasts about diabled packages,
12997 * gc'ing to free up references, unmounting all secure containers
12998 * corresponding to packages on external media, and posting a
12999 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
13000 * that we always have to post this message if status has been requested no
13003 private void unloadMediaPackages(ArrayMap<AsecInstallArgs, String> processCids, int uidArr[],
13004 final boolean reportStatus) {
13005 if (DEBUG_SD_INSTALL)
13006 Log.i(TAG, "unloading media packages");
13007 ArrayList<String> pkgList = new ArrayList<String>();
13008 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
13009 final Set<AsecInstallArgs> keys = processCids.keySet();
13010 for (AsecInstallArgs args : keys) {
13011 String pkgName = args.getPackageName();
13012 if (DEBUG_SD_INSTALL)
13013 Log.i(TAG, "Trying to unload pkg : " + pkgName);
13014 // Delete package internally
13015 PackageRemovedInfo outInfo = new PackageRemovedInfo();
13016 synchronized (mInstallLock) {
13017 boolean res = deletePackageLI(pkgName, null, false, null, null,
13018 PackageManager.DELETE_KEEP_DATA, outInfo, false);
13020 pkgList.add(pkgName);
13022 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
13023 failedList.add(args);
13029 synchronized (mPackages) {
13030 // We didn't update the settings after removing each package;
13031 // write them now for all packages.
13032 mSettings.writeLPr();
13035 // We have to absolutely send UPDATED_MEDIA_STATUS only
13036 // after confirming that all the receivers processed the ordered
13037 // broadcast when packages get disabled, force a gc to clean things up.
13038 // and unload all the containers.
13039 if (pkgList.size() > 0) {
13040 sendResourcesChangedBroadcast(false, false, pkgList, uidArr,
13041 new IIntentReceiver.Stub() {
13042 public void performReceive(Intent intent, int resultCode, String data,
13043 Bundle extras, boolean ordered, boolean sticky,
13044 int sendingUser) throws RemoteException {
13045 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
13046 reportStatus ? 1 : 0, 1, keys);
13047 mHandler.sendMessage(msg);
13051 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
13053 mHandler.sendMessage(msg);
13059 public void movePackage(final String packageName, final IPackageMoveObserver observer,
13061 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
13062 UserHandle user = new UserHandle(UserHandle.getCallingUserId());
13063 int returnCode = PackageManager.MOVE_SUCCEEDED;
13064 int currInstallFlags = 0;
13065 int newInstallFlags = 0;
13067 File codeFile = null;
13068 String installerPackageName = null;
13069 String packageAbiOverride = null;
13072 synchronized (mPackages) {
13073 final PackageParser.Package pkg = mPackages.get(packageName);
13074 final PackageSetting ps = mSettings.mPackages.get(packageName);
13075 if (pkg == null || ps == null) {
13076 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
13078 // Disable moving fwd locked apps and system packages
13079 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
13080 Slog.w(TAG, "Cannot move system application");
13081 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
13082 } else if (pkg.mOperationPending) {
13083 Slog.w(TAG, "Attempt to move package which has pending operations");
13084 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
13086 // Find install location first
13087 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
13088 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
13089 Slog.w(TAG, "Ambigous flags specified for move location.");
13090 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
13092 newInstallFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
13093 ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
13094 currInstallFlags = isExternal(pkg)
13095 ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
13097 if (newInstallFlags == currInstallFlags) {
13098 Slog.w(TAG, "No move required. Trying to move to same location");
13099 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
13101 if (isForwardLocked(pkg)) {
13102 currInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK;
13103 newInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK;
13107 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
13108 pkg.mOperationPending = true;
13112 codeFile = new File(pkg.codePath);
13113 installerPackageName = ps.installerPackageName;
13114 packageAbiOverride = ps.cpuAbiOverrideString;
13118 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
13120 observer.packageMoved(packageName, returnCode);
13121 } catch (RemoteException ignored) {
13126 final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {
13128 public void onUserActionRequired(Intent intent) throws RemoteException {
13129 throw new IllegalStateException();
13133 public void onPackageInstalled(String basePackageName, int returnCode, String msg,
13134 Bundle extras) throws RemoteException {
13135 Slog.d(TAG, "Install result for move: "
13136 + PackageManager.installStatusToString(returnCode, msg));
13138 // We usually have a new package now after the install, but if
13139 // we failed we need to clear the pending flag on the original
13141 synchronized (mPackages) {
13142 final PackageParser.Package pkg = mPackages.get(packageName);
13144 pkg.mOperationPending = false;
13148 final int status = PackageManager.installStatusToPublicStatus(returnCode);
13150 case PackageInstaller.STATUS_SUCCESS:
13151 observer.packageMoved(packageName, PackageManager.MOVE_SUCCEEDED);
13153 case PackageInstaller.STATUS_FAILURE_STORAGE:
13154 observer.packageMoved(packageName, PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE);
13157 observer.packageMoved(packageName, PackageManager.MOVE_FAILED_INTERNAL_ERROR);
13163 // Treat a move like reinstalling an existing app, which ensures that we
13164 // process everythign uniformly, like unpacking native libraries.
13165 newInstallFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
13167 final Message msg = mHandler.obtainMessage(INIT_COPY);
13168 final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
13169 msg.obj = new InstallParams(origin, installObserver, newInstallFlags,
13170 installerPackageName, null, user, packageAbiOverride);
13171 mHandler.sendMessage(msg);
13175 public boolean setInstallLocation(int loc) {
13176 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
13178 if (getInstallLocation() == loc) {
13181 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
13182 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
13183 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
13184 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
13191 public int getInstallLocation() {
13192 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
13193 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION,
13194 PackageHelper.APP_INSTALL_AUTO);
13197 /** Called by UserManagerService */
13198 void cleanUpUserLILPw(UserManagerService userManager, int userHandle) {
13199 mDirtyUsers.remove(userHandle);
13200 mSettings.removeUserLPw(userHandle);
13201 mPendingBroadcasts.remove(userHandle);
13202 if (mInstaller != null) {
13203 // Technically, we shouldn't be doing this with the package lock
13204 // held. However, this is very rare, and there is already so much
13205 // other disk I/O going on, that we'll let it slide for now.
13206 mInstaller.removeUserDataDirs(userHandle);
13208 mUserNeedsBadging.delete(userHandle);
13209 removeUnusedPackagesLILPw(userManager, userHandle);
13213 * We're removing userHandle and would like to remove any downloaded packages
13214 * that are no longer in use by any other user.
13215 * @param userHandle the user being removed
13217 private void removeUnusedPackagesLILPw(UserManagerService userManager, final int userHandle) {
13218 final boolean DEBUG_CLEAN_APKS = false;
13219 int [] users = userManager.getUserIdsLPr();
13220 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
13221 while (psit.hasNext()) {
13222 PackageSetting ps = psit.next();
13223 if (ps.pkg == null) {
13226 final String packageName = ps.pkg.packageName;
13227 // Skip over if system app
13228 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
13231 if (DEBUG_CLEAN_APKS) {
13232 Slog.i(TAG, "Checking package " + packageName);
13234 boolean keep = false;
13235 for (int i = 0; i < users.length; i++) {
13236 if (users[i] != userHandle && ps.getInstalled(users[i])) {
13238 if (DEBUG_CLEAN_APKS) {
13239 Slog.i(TAG, " Keeping package " + packageName + " for user "
13246 if (DEBUG_CLEAN_APKS) {
13247 Slog.i(TAG, " Removing package " + packageName);
13249 mHandler.post(new Runnable() {
13250 public void run() {
13251 deletePackageX(packageName, userHandle, 0);
13258 /** Called by UserManagerService */
13259 void createNewUserLILPw(int userHandle, File path) {
13260 if (mInstaller != null) {
13261 mInstaller.createUserConfig(userHandle);
13262 mSettings.createNewUserLILPw(this, mInstaller, userHandle, path);
13267 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
13268 mContext.enforceCallingOrSelfPermission(
13269 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
13270 "Only package verification agents can read the verifier device identity");
13272 synchronized (mPackages) {
13273 return mSettings.getVerifierDeviceIdentityLPw();
13278 public void setPermissionEnforced(String permission, boolean enforced) {
13279 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
13280 if (READ_EXTERNAL_STORAGE.equals(permission)) {
13281 synchronized (mPackages) {
13282 if (mSettings.mReadExternalStorageEnforced == null
13283 || mSettings.mReadExternalStorageEnforced != enforced) {
13284 mSettings.mReadExternalStorageEnforced = enforced;
13285 mSettings.writeLPr();
13288 // kill any non-foreground processes so we restart them and
13289 // grant/revoke the GID.
13290 final IActivityManager am = ActivityManagerNative.getDefault();
13292 final long token = Binder.clearCallingIdentity();
13294 am.killProcessesBelowForeground("setPermissionEnforcement");
13295 } catch (RemoteException e) {
13297 Binder.restoreCallingIdentity(token);
13301 throw new IllegalArgumentException("No selective enforcement for " + permission);
13307 public boolean isPermissionEnforced(String permission) {
13312 public boolean isStorageLow() {
13313 final long token = Binder.clearCallingIdentity();
13315 final DeviceStorageMonitorInternal
13316 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
13318 return dsm.isMemoryLow();
13323 Binder.restoreCallingIdentity(token);
13328 public IPackageInstaller getPackageInstaller() {
13329 return mInstallerService;
13332 private boolean userNeedsBadging(int userId) {
13333 int index = mUserNeedsBadging.indexOfKey(userId);
13335 final UserInfo userInfo;
13336 final long token = Binder.clearCallingIdentity();
13338 userInfo = sUserManager.getUserInfo(userId);
13340 Binder.restoreCallingIdentity(token);
13343 if (userInfo != null && userInfo.isManagedProfile()) {
13348 mUserNeedsBadging.put(userId, b);
13351 return mUserNeedsBadging.valueAt(index);
13355 public KeySet getKeySetByAlias(String packageName, String alias) {
13356 if (packageName == null || alias == null) {
13359 synchronized(mPackages) {
13360 final PackageParser.Package pkg = mPackages.get(packageName);
13362 Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
13363 throw new IllegalArgumentException("Unknown package: " + packageName);
13365 KeySetManagerService ksms = mSettings.mKeySetManagerService;
13366 return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
13371 public KeySet getSigningKeySet(String packageName) {
13372 if (packageName == null) {
13375 synchronized(mPackages) {
13376 final PackageParser.Package pkg = mPackages.get(packageName);
13378 Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
13379 throw new IllegalArgumentException("Unknown package: " + packageName);
13381 if (pkg.applicationInfo.uid != Binder.getCallingUid()
13382 && Process.SYSTEM_UID != Binder.getCallingUid()) {
13383 throw new SecurityException("May not access signing KeySet of other apps.");
13385 KeySetManagerService ksms = mSettings.mKeySetManagerService;
13386 return new KeySet(ksms.getSigningKeySetByPackageNameLPr(packageName));
13391 public boolean isPackageSignedByKeySet(String packageName, KeySet ks) {
13392 if (packageName == null || ks == null) {
13395 synchronized(mPackages) {
13396 final PackageParser.Package pkg = mPackages.get(packageName);
13398 Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
13399 throw new IllegalArgumentException("Unknown package: " + packageName);
13401 IBinder ksh = ks.getToken();
13402 if (ksh instanceof KeySetHandle) {
13403 KeySetManagerService ksms = mSettings.mKeySetManagerService;
13404 return ksms.packageIsSignedByLPr(packageName, (KeySetHandle) ksh);
13411 public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks) {
13412 if (packageName == null || ks == null) {
13415 synchronized(mPackages) {
13416 final PackageParser.Package pkg = mPackages.get(packageName);
13418 Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
13419 throw new IllegalArgumentException("Unknown package: " + packageName);
13421 IBinder ksh = ks.getToken();
13422 if (ksh instanceof KeySetHandle) {
13423 KeySetManagerService ksms = mSettings.mKeySetManagerService;
13424 return ksms.packageIsSignedByExactlyLPr(packageName, (KeySetHandle) ksh);
13430 public void getUsageStatsIfNoPackageUsageInfo() {
13431 if (!mPackageUsage.isHistoricalPackageUsageAvailable()) {
13432 UsageStatsManager usm = (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
13434 throw new IllegalStateException("UsageStatsManager must be initialized");
13436 long now = System.currentTimeMillis();
13437 Map<String, UsageStats> stats = usm.queryAndAggregateUsageStats(now - mDexOptLRUThresholdInMills, now);
13438 for (Map.Entry<String, UsageStats> entry : stats.entrySet()) {
13439 String packageName = entry.getKey();
13440 PackageParser.Package pkg = mPackages.get(packageName);
13444 UsageStats usage = entry.getValue();
13445 pkg.mLastPackageUsageTimeInMills = usage.getLastTimeUsed();
13446 mPackageUsage.mIsHistoricalPackageUsageAvailable = true;