blob: 0862153c0c444804dc8292ed8f95ef8a5cd8787f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Kenny Rootcf0b38c2011-03-22 14:17:59 -070017package com.android.server.pm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Jeff Sharkey854b2b12012-04-13 16:03:40 -070019import static android.Manifest.permission.GRANT_REVOKE_PERMISSIONS;
20import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
Kenny Root27989422011-02-23 16:28:26 -080021import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
22import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -080023import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
Dianne Hackborn0ac30312011-06-17 14:49:23 -070024import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
Kenny Root27989422011-02-23 16:28:26 -080025import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Jeff Sharkey854b2b12012-04-13 16:03:40 -070026import static com.android.internal.util.ArrayUtils.appendInt;
27import static com.android.internal.util.ArrayUtils.removeInt;
Kenny Rootddbe50d2012-09-06 13:18:37 -070028import static libcore.io.OsConstants.S_IRWXU;
29import static libcore.io.OsConstants.S_IRGRP;
30import static libcore.io.OsConstants.S_IXGRP;
31import static libcore.io.OsConstants.S_IROTH;
32import static libcore.io.OsConstants.S_IXOTH;
Kenny Root27989422011-02-23 16:28:26 -080033
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080034import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import com.android.internal.app.ResolverActivity;
Kenny Root85387d72010-08-26 10:13:11 -070036import com.android.internal.content.NativeLibraryHelper;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080037import com.android.internal.content.PackageHelper;
Dianne Hackborn8c841092013-06-24 13:46:13 -070038import com.android.internal.util.FastPrintWriter;
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070039import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080040import com.android.internal.util.XmlUtils;
Kenny Rootcf0b38c2011-03-22 14:17:59 -070041import com.android.server.EventLogTags;
42import com.android.server.IntentResolver;
Jeff Brown6f357d32014-01-15 20:40:55 -080043import com.android.server.ServiceThread;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044
Adam Lesinskief2ea1f2013-12-05 16:48:06 -080045import com.android.server.LocalServices;
Dianne Hackbornfa012b32013-05-10 15:23:28 -070046import com.android.server.Watchdog;
Jason parksa3cdaa52011-01-13 14:15:43 -060047import org.xmlpull.v1.XmlPullParser;
48import org.xmlpull.v1.XmlPullParserException;
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070049import org.xmlpull.v1.XmlSerializer;
Jason parksa3cdaa52011-01-13 14:15:43 -060050
rich canningsa2064df2012-09-30 14:52:41 -070051import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.app.ActivityManagerNative;
53import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080054import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080055import android.app.backup.IBackupManager;
Kenny Root5ab21572011-07-27 11:11:19 -070056import android.content.BroadcastReceiver;
Jason parksa3cdaa52011-01-13 14:15:43 -060057import android.content.ComponentName;
Kenny Root27989422011-02-23 16:28:26 -080058import android.content.Context;
Dianne Hackbornecb0e632010-04-07 20:22:55 -070059import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.Intent;
61import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070062import android.content.IntentSender;
Jason parks1125d782011-01-12 09:47:26 -060063import android.content.ServiceConnection;
Jason parksa3cdaa52011-01-13 14:15:43 -060064import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.ActivityInfo;
66import android.content.pm.ApplicationInfo;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070067import android.content.pm.ContainerEncryptionParams;
Dianne Hackborn49237342009-08-27 20:08:01 -070068import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageDeleteObserver;
71import android.content.pm.IPackageInstallObserver;
72import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080073import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.content.pm.IPackageStatsObserver;
75import android.content.pm.InstrumentationInfo;
Dianne Hackborn7767eac2012-08-23 18:25:40 -070076import android.content.pm.PackageCleanItem;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080078import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.content.pm.PackageManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060080import android.content.pm.PackageParser;
Dianne Hackborn7767eac2012-08-23 18:25:40 -070081import android.content.pm.PackageUserState;
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -070082import android.content.pm.PackageParser.ActivityIntentInfo;
Kenny Root27989422011-02-23 16:28:26 -080083import android.content.pm.PackageStats;
Kenny Root0e2c0f32011-04-15 17:50:10 -070084import android.content.pm.ParceledListSlice;
Jason parksa3cdaa52011-01-13 14:15:43 -060085import android.content.pm.PermissionGroupInfo;
Kenny Root27989422011-02-23 16:28:26 -080086import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.content.pm.ProviderInfo;
88import android.content.pm.ResolveInfo;
89import android.content.pm.ServiceInfo;
90import android.content.pm.Signature;
Kenny Root5ab21572011-07-27 11:11:19 -070091import android.content.pm.ManifestDigest;
rich cannings706e8ba2012-08-20 13:20:14 -070092import android.content.pm.VerificationParams;
Kenny Root0aaa0d92011-09-12 16:42:55 -070093import android.content.pm.VerifierDeviceIdentity;
Kenny Root05ca4c92011-09-15 10:36:25 -070094import android.content.pm.VerifierInfo;
Jose Limabb9682e2013-08-16 16:14:32 -070095import android.content.res.Resources;
Adam Lesinskief2ea1f2013-12-05 16:48:06 -080096import android.hardware.display.DisplayManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.net.Uri;
98import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070099import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Bundle;
Kenny Root27989422011-02-23 16:28:26 -0800101import android.os.Environment;
102import android.os.FileObserver;
103import android.os.FileUtils;
104import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800106import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700107import android.os.Looper;
108import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.os.ParcelFileDescriptor;
111import android.os.Process;
Kenny Root27989422011-02-23 16:28:26 -0800112import android.os.RemoteException;
rpcraig554cb0c2012-07-05 06:41:43 -0400113import android.os.SELinux;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.os.ServiceManager;
115import android.os.SystemClock;
116import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700117import android.os.UserHandle;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700118import android.os.Environment.UserEnvironment;
Kenny Rootd72317a2013-04-01 15:59:59 -0700119import android.os.UserManager;
Kenny Rootd72317a2013-04-01 15:59:59 -0700120import android.security.KeyStore;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800121import android.security.SystemKeyStore;
Jose Limabb9682e2013-08-16 16:14:32 -0700122import android.text.TextUtils;
Kenny Root27989422011-02-23 16:28:26 -0800123import android.util.DisplayMetrics;
124import android.util.EventLog;
125import android.util.Log;
126import android.util.LogPrinter;
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -0700127import android.util.PrintStreamPrinter;
Kenny Root27989422011-02-23 16:28:26 -0800128import android.util.Slog;
129import android.util.SparseArray;
130import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import android.view.Display;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -0700133import java.io.BufferedOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134import java.io.File;
135import java.io.FileDescriptor;
136import java.io.FileInputStream;
137import java.io.FileNotFoundException;
138import java.io.FileOutputStream;
139import java.io.FileReader;
140import java.io.FilenameFilter;
141import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800143import java.security.NoSuchAlgorithmException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700144import java.security.PublicKey;
145import java.security.cert.CertificateException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800146import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147import java.util.ArrayList;
148import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700149import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150import java.util.Collections;
151import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800152import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153import java.util.HashMap;
154import java.util.HashSet;
155import java.util.Iterator;
156import java.util.List;
157import java.util.Map;
158import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159
Kenny Root66269ea2011-07-12 14:14:01 -0700160import libcore.io.ErrnoException;
Kenny Root3f99afc2012-04-14 10:13:10 -0700161import libcore.io.IoUtils;
Kenny Root66269ea2011-07-12 14:14:01 -0700162import libcore.io.Libcore;
Kenny Root786cbca2012-08-16 11:10:58 -0700163import libcore.io.StructStat;
Kenny Root66269ea2011-07-12 14:14:01 -0700164
Jose Limabb9682e2013-08-16 16:14:32 -0700165import com.android.internal.R;
Adam Lesinskief2ea1f2013-12-05 16:48:06 -0800166import com.android.server.storage.DeviceStorageMonitorInternal;
Jose Limabb9682e2013-08-16 16:14:32 -0700167
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700168/**
169 * Keep track of all those .apks everywhere.
170 *
171 * This is very central to the platform's security; please run the unit
172 * tests whenever making modifications here:
173 *
174mmm frameworks/base/tests/AndroidTests
175adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
176adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700177 *
178 * {@hide}
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700179 */
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700180public class PackageManagerService extends IPackageManager.Stub {
181 static final String TAG = "PackageManager";
182 static final boolean DEBUG_SETTINGS = false;
Dianne Hackbornc895be72013-03-11 17:48:43 -0700183 static final boolean DEBUG_PREFERRED = false;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700184 static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800185 private static final boolean DEBUG_INSTALL = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800186 private static final boolean DEBUG_REMOVE = false;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700187 private static final boolean DEBUG_BROADCASTS = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800188 private static final boolean DEBUG_SHOW_INFO = false;
189 private static final boolean DEBUG_PACKAGE_INFO = false;
190 private static final boolean DEBUG_INTENT_MATCHING = false;
191 private static final boolean DEBUG_PACKAGE_SCANNING = false;
192 private static final boolean DEBUG_APP_DIR_OBSERVER = false;
Kenny Root05ca4c92011-09-15 10:36:25 -0700193 private static final boolean DEBUG_VERIFY = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400196 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700197 private static final int NFC_UID = Process.NFC_UID;
Jaikumar Ganesh1abb1cb2012-01-25 16:14:50 -0800198 private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
Dianne Hackborn514074f2013-02-11 10:52:46 -0800199 private static final int SHELL_UID = Process.SHELL_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 private static final boolean GET_CERTIFICATES = true;
202
203 private static final int REMOVE_EVENTS =
204 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
205 private static final int ADD_EVENTS =
206 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
207
208 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800209 // Suffix used during package installation when copying/moving
210 // package apks to install directory.
211 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212
213 static final int SCAN_MONITOR = 1<<0;
214 static final int SCAN_NO_DEX = 1<<1;
215 static final int SCAN_FORCE_DEX = 1<<2;
216 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800217 static final int SCAN_NEW_INSTALL = 1<<4;
218 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700219 static final int SCAN_UPDATE_TIME = 1<<6;
Dianne Hackborn661cd522011-08-22 00:26:20 -0700220 static final int SCAN_DEFER_DEX = 1<<7;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -0700221 static final int SCAN_BOOTING = 1<<8;
Narayan Kamath65048bd2013-12-16 18:18:12 +0000222 static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<9;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700224 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700225
Kenny Root5ab21572011-07-27 11:11:19 -0700226 /**
Christopher Tatee6f81cf2013-10-23 17:28:27 -0700227 * Timeout (in milliseconds) after which the watchdog should declare that
228 * our handler thread is wedged. The usual default for such things is one
229 * minute but we sometimes do very lengthy I/O operations on this thread,
230 * such as installing multi-gigabyte applications, so ours needs to be longer.
231 */
232 private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
233
234 /**
Kenny Root5ab21572011-07-27 11:11:19 -0700235 * Whether verification is enabled by default.
236 */
rich cannings36c67c22012-09-16 16:20:23 -0700237 private static final boolean DEFAULT_VERIFY_ENABLE = true;
Kenny Root5ab21572011-07-27 11:11:19 -0700238
239 /**
240 * The default maximum time to wait for the verification agent to return in
241 * milliseconds.
242 */
rich canningsaa8513e2012-05-21 16:15:23 -0700243 private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
Kenny Root5ab21572011-07-27 11:11:19 -0700244
rich canningsa6cfe522012-05-21 15:50:56 -0700245 /**
246 * The default response for package verification timeout.
247 *
248 * This can be either PackageManager.VERIFICATION_ALLOW or
249 * PackageManager.VERIFICATION_REJECT.
250 */
251 private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
252
Kenny Root11128572010-10-11 10:51:32 -0700253 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
254
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800255 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700256 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800257 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700258
Kenny Root05ca4c92011-09-15 10:36:25 -0700259 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
260
Kenny Root85387d72010-08-26 10:13:11 -0700261 private static final String LIB_DIR_NAME = "lib";
262
Kenny Rootc78a8072010-07-27 15:18:38 -0700263 static final String mTempContainerPrefix = "smdl2tmp";
264
Jeff Brown6f357d32014-01-15 20:40:55 -0800265 final ServiceThread mHandlerThread;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700266 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Dianne Hackborn851a5412009-05-08 12:06:44 -0700268 final int mSdkVersion = Build.VERSION.SDK_INT;
269 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
270 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 final Context mContext;
273 final boolean mFactoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700274 final boolean mOnlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700275 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 final DisplayMetrics mMetrics;
277 final int mDefParseFlags;
278 final String[] mSeparateProcesses;
279
280 // This is where all application persistent data goes.
281 final File mAppDataDir;
282
Amith Yamasani0b285492011-04-14 17:35:23 -0700283 // This is where all application persistent data goes for secondary users.
284 final File mUserAppDataDir;
285
Kenny Root51a573c2012-05-17 13:30:28 -0700286 /** The location for ASEC container files on internal storage. */
287 final String mAsecInternalPath;
288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 // This is the object monitoring the framework dir.
290 final FileObserver mFrameworkInstallObserver;
291
292 // This is the object monitoring the system app dir.
293 final FileObserver mSystemInstallObserver;
294
Christopher Tateccbf84f2013-05-08 15:25:41 -0700295 // This is the object monitoring the privileged system app dir.
296 final FileObserver mPrivilegedInstallObserver;
297
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700298 // This is the object monitoring the system app dir.
299 final FileObserver mVendorInstallObserver;
300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 // This is the object monitoring mAppInstallDir.
302 final FileObserver mAppInstallObserver;
303
304 // This is the object monitoring mDrmAppPrivateInstallDir.
305 final FileObserver mDrmAppInstallObserver;
306
Kenny Rootddbe50d2012-09-06 13:18:37 -0700307 // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 // LOCK HELD. Can be called with mInstallLock held.
309 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 final File mAppInstallDir;
312
Kenny Rootddbe50d2012-09-06 13:18:37 -0700313 /**
314 * Directory to which applications installed internally have native
315 * libraries copied.
316 */
317 private File mAppLibInstallDir;
318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
320 // apps.
321 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 // Lock for state used when installing and doing other long running
326 // operations. Methods that must be called with this lock held have
327 // the prefix "LI".
328 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 // These are the directories in the 3rd party applications installed dir
331 // that we have currently loaded packages from. Keys are the application's
332 // installed zip file (absolute codePath), and values are Package.
333 final HashMap<String, PackageParser.Package> mAppDirs =
334 new HashMap<String, PackageParser.Package>();
335
336 // Information for the parser to write more useful error messages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 int mLastScanError;
338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 // Keys are String (package name), values are Package. This also serves
342 // as the lock for the global state. Methods that must be called with
343 // this lock held have the prefix "LP".
344 final HashMap<String, PackageParser.Package> mPackages =
345 new HashMap<String, PackageParser.Package>();
346
347 final Settings mSettings;
348 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349
350 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
351 int[] mGlobalGids;
352
353 // These are the built-in uid -> permission mappings that were read from the
354 // etc/permissions.xml file.
355 final SparseArray<HashSet<String>> mSystemPermissions =
356 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800357
Dianne Hackbornc895be72013-03-11 17:48:43 -0700358 static final class SharedLibraryEntry {
359 final String path;
360 final String apk;
361
362 SharedLibraryEntry(String _path, String _apk) {
363 path = _path;
364 apk = _apk;
365 }
366 }
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 // These are the built-in shared libraries that were read from the
369 // etc/permissions.xml file.
Dianne Hackbornc895be72013-03-11 17:48:43 -0700370 final HashMap<String, SharedLibraryEntry> mSharedLibraries
371 = new HashMap<String, SharedLibraryEntry>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800372
Dianne Hackborn49237342009-08-27 20:08:01 -0700373 // Temporary for building the final shared libraries for an .apk.
374 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800375
Dianne Hackborn49237342009-08-27 20:08:01 -0700376 // These are the features this devices supports that were read from the
377 // etc/permissions.xml file.
378 final HashMap<String, FeatureInfo> mAvailableFeatures =
379 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800380
Robert Craig0f40dc92013-03-25 06:33:03 -0400381 // If mac_permissions.xml was found for seinfo labeling.
382 boolean mFoundPolicyFile;
383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 // All available activities, for your resolving pleasure.
385 final ActivityIntentResolver mActivities =
386 new ActivityIntentResolver();
387
388 // All available receivers, for your resolving pleasure.
389 final ActivityIntentResolver mReceivers =
390 new ActivityIntentResolver();
391
392 // All available services, for your resolving pleasure.
393 final ServiceIntentResolver mServices = new ServiceIntentResolver();
394
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700395 // All available providers, for your resolving pleasure.
396 final ProviderIntentResolver mProviders = new ProviderIntentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397
398 // Mapping from provider base names (first directory in content URI codePath)
399 // to the provider information.
Jeff Sharkey85f5f812013-10-07 10:16:12 -0700400 final HashMap<String, PackageParser.Provider> mProvidersByAuthority =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 new HashMap<String, PackageParser.Provider>();
402
403 // Mapping from instrumentation class names to info about them.
404 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
405 new HashMap<ComponentName, PackageParser.Instrumentation>();
406
407 // Mapping from permission names to info about them.
408 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
409 new HashMap<String, PackageParser.PermissionGroup>();
410
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800411 // Packages whose data we have transfered into another package, thus
412 // should no longer exist.
413 final HashSet<String> mTransferedPackages = new HashSet<String>();
414
Dianne Hackborn854060af2009-07-09 18:14:31 -0700415 // Broadcast actions that are only available to the system.
416 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800417
Kenny Root5ab21572011-07-27 11:11:19 -0700418 /** List of packages waiting for verification. */
Kenny Root05ca4c92011-09-15 10:36:25 -0700419 final SparseArray<PackageVerificationState> mPendingVerification
420 = new SparseArray<PackageVerificationState>();
Kenny Root5ab21572011-07-27 11:11:19 -0700421
Dianne Hackbornc895be72013-03-11 17:48:43 -0700422 HashSet<PackageParser.Package> mDeferredDexOpt = null;
Dianne Hackborn661cd522011-08-22 00:26:20 -0700423
Kenny Root5ab21572011-07-27 11:11:19 -0700424 /** Token for keys in mPendingVerification. */
425 private int mPendingVerificationToken = 0;
426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 boolean mSystemReady;
428 boolean mSafeMode;
429 boolean mHasSystemUidErrors;
430
431 ApplicationInfo mAndroidApplication;
432 final ActivityInfo mResolveActivity = new ActivityInfo();
433 final ResolveInfo mResolveInfo = new ResolveInfo();
434 ComponentName mResolveComponentName;
435 PackageParser.Package mPlatformPackage;
Jose Limabb9682e2013-08-16 16:14:32 -0700436 ComponentName mCustomResolverComponentName;
437
438 boolean mResolverReplaced = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700440 // Set of pending broadcasts for aggregating enable/disable of components.
Christopher Tate1e08f5c2013-05-02 13:27:27 -0700441 static class PendingPackageBroadcasts {
442 // for each user id, a map of <package name -> components within that package>
443 final SparseArray<HashMap<String, ArrayList<String>>> mUidMap;
444
445 public PendingPackageBroadcasts() {
Dianne Hackbornf4bf0ae2013-05-20 18:42:16 -0700446 mUidMap = new SparseArray<HashMap<String, ArrayList<String>>>(2);
Christopher Tate1e08f5c2013-05-02 13:27:27 -0700447 }
448
449 public ArrayList<String> get(int userId, String packageName) {
450 HashMap<String, ArrayList<String>> packages = getOrAllocate(userId);
451 return packages.get(packageName);
452 }
453
454 public void put(int userId, String packageName, ArrayList<String> components) {
455 HashMap<String, ArrayList<String>> packages = getOrAllocate(userId);
456 packages.put(packageName, components);
457 }
458
459 public void remove(int userId, String packageName) {
460 HashMap<String, ArrayList<String>> packages = mUidMap.get(userId);
461 if (packages != null) {
462 packages.remove(packageName);
463 }
464 }
465
466 public void remove(int userId) {
467 mUidMap.remove(userId);
468 }
469
470 public int userIdCount() {
471 return mUidMap.size();
472 }
473
474 public int userIdAt(int n) {
475 return mUidMap.keyAt(n);
476 }
477
478 public HashMap<String, ArrayList<String>> packagesForUserId(int userId) {
479 return mUidMap.get(userId);
480 }
481
482 public int size() {
483 // total number of pending broadcast entries across all userIds
484 int num = 0;
485 for (int i = 0; i< mUidMap.size(); i++) {
486 num += mUidMap.valueAt(i).size();
487 }
488 return num;
489 }
490
491 public void clear() {
492 mUidMap.clear();
493 }
494
495 private HashMap<String, ArrayList<String>> getOrAllocate(int userId) {
496 HashMap<String, ArrayList<String>> map = mUidMap.get(userId);
497 if (map == null) {
498 map = new HashMap<String, ArrayList<String>>();
499 mUidMap.put(userId, map);
500 }
501 return map;
502 }
503 }
504 final PendingPackageBroadcasts mPendingBroadcasts = new PendingPackageBroadcasts();
505
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800506 // Service Connection to remote media container service to copy
507 // package uri's from external media onto secure containers
508 // or internal storage.
509 private IMediaContainerService mContainerService = null;
510
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700511 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800512 static final int MCS_BOUND = 3;
513 static final int END_COPY = 4;
514 static final int INIT_COPY = 5;
515 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800516 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800517 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800518 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800519 static final int MCS_RECONNECT = 10;
520 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700521 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700522 static final int WRITE_SETTINGS = 13;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700523 static final int WRITE_PACKAGE_RESTRICTIONS = 14;
Kenny Root5ab21572011-07-27 11:11:19 -0700524 static final int PACKAGE_VERIFIED = 15;
525 static final int CHECK_PENDING_VERIFICATION = 16;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700526
527 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800528
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700529 // Delay time in millisecs
530 static final int BROADCAST_DELAY = 10 * 1000;
Kenny Root9718cf52011-02-23 16:45:26 -0800531
Amith Yamasani258848d2012-08-10 17:06:33 -0700532 static UserManagerService sUserManager;
Amith Yamasani0b285492011-04-14 17:35:23 -0700533
Amith Yamasani483f3b02012-03-13 16:08:00 -0700534 // Stores a list of users whose package restrictions file needs to be updated
535 private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
536
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800537 final private DefaultContainerConnection mDefContainerConn =
538 new DefaultContainerConnection();
539 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800540 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800541 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800542 IMediaContainerService imcs =
543 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800544 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800545 }
546
547 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800548 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800549 }
550 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700551
Christopher Tate1bb69062010-02-19 17:02:12 -0800552 // Recordkeeping of restore-after-install operations that are currently in flight
553 // between the Package Manager and the Backup Manager
554 class PostInstallData {
555 public InstallArgs args;
556 public PackageInstalledInfo res;
557
558 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
559 args = _a;
560 res = _r;
561 }
562 };
563 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
564 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
565
Kenny Root05ca4c92011-09-15 10:36:25 -0700566 private final String mRequiredVerifierPackage;
567
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700568 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800569 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800570 final ArrayList<HandlerParams> mPendingInstalls =
571 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800572
573 private boolean connectToService() {
574 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
575 " DefaultContainerService");
576 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700577 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Amith Yamasani27b89e62013-01-16 12:30:11 -0800578 if (mContext.bindServiceAsUser(service, mDefContainerConn,
579 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700580 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800581 mBound = true;
582 return true;
583 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700584 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800585 return false;
586 }
587
588 private void disconnectService() {
589 mContainerService = null;
590 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700591 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800592 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700593 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800594 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800595
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700596 PackageHandler(Looper looper) {
597 super(looper);
598 }
Dianne Hackborn7d608422011-08-07 16:24:18 -0700599
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700600 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700601 try {
602 doHandleMessage(msg);
603 } finally {
604 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
605 }
606 }
607
608 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700609 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800610 case INIT_COPY: {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800611 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800612 int idx = mPendingInstalls.size();
Dianne Hackbornc895be72013-03-11 17:48:43 -0700613 if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800614 // If a bind was already initiated we dont really
615 // need to do anything. The pending install
616 // will be processed later on.
617 if (!mBound) {
618 // If this is the only one pending we might
619 // have to bind to the service again.
620 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800621 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800622 params.serviceError();
623 return;
624 } else {
625 // Once we bind to the service, the first
626 // pending request will be processed.
627 mPendingInstalls.add(idx, params);
628 }
629 } else {
630 mPendingInstalls.add(idx, params);
631 // Already bound to the service. Just make
632 // sure we trigger off processing the first request.
633 if (idx == 0) {
634 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800635 }
636 }
637 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800638 }
639 case MCS_BOUND: {
Kenny Root5ab21572011-07-27 11:11:19 -0700640 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800641 if (msg.obj != null) {
642 mContainerService = (IMediaContainerService) msg.obj;
643 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800644 if (mContainerService == null) {
645 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800646 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800647 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800648 // Indicate service bind error
649 params.serviceError();
650 }
651 mPendingInstalls.clear();
652 } else if (mPendingInstalls.size() > 0) {
653 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800654 if (params != null) {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700655 if (params.startCopy()) {
656 // We are done... look for more work or to
657 // go idle.
658 if (DEBUG_SD_INSTALL) Log.i(TAG,
659 "Checking for more work or unbind...");
660 // Delete pending install
661 if (mPendingInstalls.size() > 0) {
662 mPendingInstalls.remove(0);
663 }
664 if (mPendingInstalls.size() == 0) {
665 if (mBound) {
666 if (DEBUG_SD_INSTALL) Log.i(TAG,
667 "Posting delayed MCS_UNBIND");
668 removeMessages(MCS_UNBIND);
669 Message ubmsg = obtainMessage(MCS_UNBIND);
670 // Unbind after a little delay, to avoid
671 // continual thrashing.
672 sendMessageDelayed(ubmsg, 10000);
673 }
674 } else {
675 // There are more pending requests in queue.
676 // Just post MCS_BOUND message to trigger processing
677 // of next pending install.
678 if (DEBUG_SD_INSTALL) Log.i(TAG,
679 "Posting MCS_BOUND for next woek");
680 mHandler.sendEmptyMessage(MCS_BOUND);
681 }
682 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800683 }
684 } else {
685 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800686 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800687 }
688 break;
689 }
Kenny Root5ab21572011-07-27 11:11:19 -0700690 case MCS_RECONNECT: {
691 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800692 if (mPendingInstalls.size() > 0) {
693 if (mBound) {
694 disconnectService();
695 }
696 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800697 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800698 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800699 // Indicate service bind error
700 params.serviceError();
701 }
702 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800703 }
704 }
705 break;
706 }
Kenny Root5ab21572011-07-27 11:11:19 -0700707 case MCS_UNBIND: {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700708 // If there is no actual work left, then time to unbind.
Kenny Root5ab21572011-07-27 11:11:19 -0700709 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
710
711 if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800712 if (mBound) {
Kenny Root5ab21572011-07-27 11:11:19 -0700713 if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
714
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800715 disconnectService();
716 }
Kenny Root5ab21572011-07-27 11:11:19 -0700717 } else if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800718 // There are more pending requests in queue.
719 // Just post MCS_BOUND message to trigger processing
720 // of next pending install.
721 mHandler.sendEmptyMessage(MCS_BOUND);
722 }
Kenny Root5ab21572011-07-27 11:11:19 -0700723
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800724 break;
725 }
726 case MCS_GIVE_UP: {
Kenny Root5ab21572011-07-27 11:11:19 -0700727 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
Kenny Root60f7ad82011-03-22 12:49:06 -0700728 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800729 break;
730 }
Kenny Root5ab21572011-07-27 11:11:19 -0700731 case SEND_PENDING_BROADCAST: {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800732 String packages[];
Kenny Root60f7ad82011-03-22 12:49:06 -0700733 ArrayList<String> components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700734 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700735 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700736 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700737 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800738 if (mPendingBroadcasts == null) {
739 return;
740 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700741 size = mPendingBroadcasts.size();
742 if (size <= 0) {
743 // Nothing to be done. Just return
744 return;
745 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800746 packages = new String[size];
747 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700748 uids = new int[size];
Christopher Tate1e08f5c2013-05-02 13:27:27 -0700749 int i = 0; // filling out the above arrays
750
751 for (int n = 0; n < mPendingBroadcasts.userIdCount(); n++) {
752 int packageUserId = mPendingBroadcasts.userIdAt(n);
753 Iterator<Map.Entry<String, ArrayList<String>>> it
754 = mPendingBroadcasts.packagesForUserId(packageUserId)
755 .entrySet().iterator();
756 while (it.hasNext() && i < size) {
757 Map.Entry<String, ArrayList<String>> ent = it.next();
758 packages[i] = ent.getKey();
759 components[i] = ent.getValue();
760 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
761 uids[i] = (ps != null)
762 ? UserHandle.getUid(packageUserId, ps.appId)
763 : -1;
764 i++;
765 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700766 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800767 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700768 mPendingBroadcasts.clear();
769 }
770 // Send broadcasts
771 for (int i = 0; i < size; i++) {
Kenny Root60f7ad82011-03-22 12:49:06 -0700772 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700773 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700774 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700775 break;
776 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800777 case START_CLEANING_PACKAGE: {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700778 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Jeff Sharkey752cd922012-09-23 16:25:12 -0700779 final String packageName = (String)msg.obj;
780 final int userId = msg.arg1;
781 final boolean andCode = msg.arg2 != 0;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800782 synchronized (mPackages) {
Jeff Sharkey752cd922012-09-23 16:25:12 -0700783 if (userId == UserHandle.USER_ALL) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700784 int[] users = sUserManager.getUserIds();
785 for (int user : users) {
Jeff Sharkey752cd922012-09-23 16:25:12 -0700786 mSettings.addPackageToCleanLPw(
787 new PackageCleanItem(user, packageName, andCode));
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700788 }
789 } else {
Jeff Sharkey752cd922012-09-23 16:25:12 -0700790 mSettings.addPackageToCleanLPw(
791 new PackageCleanItem(userId, packageName, andCode));
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800792 }
793 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700794 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Jeff Sharkey752cd922012-09-23 16:25:12 -0700795 startCleaningPackages();
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800796 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800797 case POST_INSTALL: {
798 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
799 PostInstallData data = mRunningInstalls.get(msg.arg1);
800 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700801 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800802
803 if (data != null) {
804 InstallArgs args = data.args;
805 PackageInstalledInfo res = data.res;
806
807 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700808 res.removedInfo.sendBroadcast(false, true, false);
Christopher Tate1bb69062010-02-19 17:02:12 -0800809 Bundle extras = new Bundle(1);
810 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackborn786b4402012-08-27 15:14:02 -0700811 // Determine the set of users who are adding this
812 // package for the first time vs. those who are seeing
813 // an update.
814 int[] firstUsers;
815 int[] updateUsers = new int[0];
816 if (res.origUsers == null || res.origUsers.length == 0) {
817 firstUsers = res.newUsers;
818 } else {
819 firstUsers = new int[0];
820 for (int i=0; i<res.newUsers.length; i++) {
821 int user = res.newUsers[i];
822 boolean isNew = true;
823 for (int j=0; j<res.origUsers.length; j++) {
824 if (res.origUsers[j] == user) {
825 isNew = false;
826 break;
827 }
828 }
829 if (isNew) {
830 int[] newFirst = new int[firstUsers.length+1];
831 System.arraycopy(firstUsers, 0, newFirst, 0,
832 firstUsers.length);
833 newFirst[firstUsers.length] = user;
834 firstUsers = newFirst;
835 } else {
836 int[] newUpdate = new int[updateUsers.length+1];
837 System.arraycopy(updateUsers, 0, newUpdate, 0,
838 updateUsers.length);
839 newUpdate[updateUsers.length] = user;
840 updateUsers = newUpdate;
841 }
842 }
843 }
844 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
845 res.pkg.applicationInfo.packageName,
846 extras, null, null, firstUsers);
Christopher Tate1bb69062010-02-19 17:02:12 -0800847 final boolean update = res.removedInfo.removedPackage != null;
848 if (update) {
849 extras.putBoolean(Intent.EXTRA_REPLACING, true);
850 }
851 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
852 res.pkg.applicationInfo.packageName,
Dianne Hackborn786b4402012-08-27 15:14:02 -0700853 extras, null, null, updateUsers);
Christopher Tate1bb69062010-02-19 17:02:12 -0800854 if (update) {
855 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
856 res.pkg.applicationInfo.packageName,
Dianne Hackborn786b4402012-08-27 15:14:02 -0700857 extras, null, null, updateUsers);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800858 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
859 null, null,
Dianne Hackborn786b4402012-08-27 15:14:02 -0700860 res.pkg.applicationInfo.packageName, null, updateUsers);
Christopher Tated15967482013-10-04 13:57:22 -0700861
862 // treat asec-hosted packages like removable media on upgrade
863 if (isForwardLocked(res.pkg) || isExternal(res.pkg)) {
864 if (DEBUG_INSTALL) {
865 Slog.i(TAG, "upgrading pkg " + res.pkg
866 + " is ASEC-hosted -> AVAILABLE");
867 }
868 int[] uidArray = new int[] { res.pkg.applicationInfo.uid };
869 ArrayList<String> pkgList = new ArrayList<String>(1);
870 pkgList.add(res.pkg.applicationInfo.packageName);
Christopher Tate8b3e3ec2014-01-08 16:54:25 -0800871 sendResourcesChangedBroadcast(true, true,
Christopher Tated15967482013-10-04 13:57:22 -0700872 pkgList,uidArray, null);
873 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800874 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700875 if (res.removedInfo.args != null) {
876 // Remove the replaced package's older resources safely now
877 deleteOld = true;
878 }
Matt Finifterf8a98ed2012-05-14 15:43:34 -0700879
880 // Log current value of "unknown sources" setting
881 EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
882 getUnknownSourcesSettings());
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700883 }
884 // Force a gc to clear up things
885 Runtime.getRuntime().gc();
886 // We delete after a gc for applications on sdcard.
887 if (deleteOld) {
888 synchronized (mInstallLock) {
889 res.removedInfo.args.doPostDeleteLI(true);
890 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800891 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800892 if (args.observer != null) {
893 try {
894 args.observer.packageInstalled(res.name, res.returnCode);
895 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800896 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800897 }
898 }
899 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800900 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800901 }
902 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700903 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700904 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
905 boolean reportStatus = msg.arg1 == 1;
906 boolean doGc = msg.arg2 == 1;
907 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
908 if (doGc) {
909 // Force a gc to clear up stale containers.
910 Runtime.getRuntime().gc();
911 }
912 if (msg.obj != null) {
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700913 @SuppressWarnings("unchecked")
Kenny Root6dceb882012-04-12 14:23:49 -0700914 Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700915 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
916 // Unload containers
917 unloadAllContainers(args);
918 }
919 if (reportStatus) {
920 try {
921 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
922 PackageHelper.getMountService().finishMediaUpdate();
923 } catch (RemoteException e) {
924 Log.e(TAG, "MountService not running?");
925 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700926 }
927 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700928 case WRITE_SETTINGS: {
929 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
930 synchronized (mPackages) {
931 removeMessages(WRITE_SETTINGS);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700932 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
Kenny Root447106f2011-03-23 11:00:15 -0700933 mSettings.writeLPr();
Amith Yamasani483f3b02012-03-13 16:08:00 -0700934 mDirtyUsers.clear();
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700935 }
936 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
937 } break;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700938 case WRITE_PACKAGE_RESTRICTIONS: {
Dianne Hackborne7f97212011-02-24 14:40:20 -0800939 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
940 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -0700941 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
942 for (int userId : mDirtyUsers) {
943 mSettings.writePackageRestrictionsLPr(userId);
944 }
945 mDirtyUsers.clear();
Dianne Hackborne7f97212011-02-24 14:40:20 -0800946 }
947 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
948 } break;
Kenny Root5ab21572011-07-27 11:11:19 -0700949 case CHECK_PENDING_VERIFICATION: {
950 final int verificationId = msg.arg1;
Kenny Root05ca4c92011-09-15 10:36:25 -0700951 final PackageVerificationState state = mPendingVerification.get(verificationId);
Kenny Root5ab21572011-07-27 11:11:19 -0700952
rich canningsd9ef3e52012-08-22 14:28:05 -0700953 if ((state != null) && !state.timeoutExtended()) {
Kenny Root05ca4c92011-09-15 10:36:25 -0700954 final InstallArgs args = state.getInstallArgs();
Kenny Roota503a0f2011-10-03 14:45:28 -0700955 Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
Kenny Root5ab21572011-07-27 11:11:19 -0700956 mPendingVerification.remove(verificationId);
957
rich canningsa6cfe522012-05-21 15:50:56 -0700958 int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
959
960 if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
rich canningsd9ef3e52012-08-22 14:28:05 -0700961 Slog.i(TAG, "Continuing with installation of "
962 + args.packageURI.toString());
963 state.setVerifierResponse(Binder.getCallingUid(),
964 PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
rich canningsd1b5cfc2012-08-29 14:49:51 -0700965 broadcastPackageVerified(verificationId, args.packageURI,
rich canningsd55deb02012-10-02 14:53:08 -0700966 PackageManager.VERIFICATION_ALLOW,
967 state.getInstallArgs().getUser());
rich canningsd9ef3e52012-08-22 14:28:05 -0700968 try {
969 ret = args.copyApk(mContainerService, true);
970 } catch (RemoteException e) {
971 Slog.e(TAG, "Could not contact the ContainerService");
972 }
rich canningsd1b5cfc2012-08-29 14:49:51 -0700973 } else {
974 broadcastPackageVerified(verificationId, args.packageURI,
rich canningsd55deb02012-10-02 14:53:08 -0700975 PackageManager.VERIFICATION_REJECT,
976 state.getInstallArgs().getUser());
rich canningsa6cfe522012-05-21 15:50:56 -0700977 }
978
Kenny Root5ab21572011-07-27 11:11:19 -0700979 processPendingInstall(args, ret);
Kenny Root5ab21572011-07-27 11:11:19 -0700980 mHandler.sendEmptyMessage(MCS_UNBIND);
981 }
Kenny Root5ab21572011-07-27 11:11:19 -0700982 break;
983 }
984 case PACKAGE_VERIFIED: {
985 final int verificationId = msg.arg1;
Kenny Root5ab21572011-07-27 11:11:19 -0700986
Kenny Root05ca4c92011-09-15 10:36:25 -0700987 final PackageVerificationState state = mPendingVerification.get(verificationId);
988 if (state == null) {
Kenny Roota503a0f2011-10-03 14:45:28 -0700989 Slog.w(TAG, "Invalid verification token " + verificationId + " received");
Kenny Root5ab21572011-07-27 11:11:19 -0700990 break;
991 }
992
Kenny Root05ca4c92011-09-15 10:36:25 -0700993 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
Kenny Root5ab21572011-07-27 11:11:19 -0700994
Kenny Root05ca4c92011-09-15 10:36:25 -0700995 state.setVerifierResponse(response.callerUid, response.code);
996
997 if (state.isVerificationComplete()) {
998 mPendingVerification.remove(verificationId);
999
1000 final InstallArgs args = state.getInstallArgs();
1001
1002 int ret;
1003 if (state.isInstallAllowed()) {
1004 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
rich canningsd1b5cfc2012-08-29 14:49:51 -07001005 broadcastPackageVerified(verificationId, args.packageURI,
rich canningsd55deb02012-10-02 14:53:08 -07001006 response.code, state.getInstallArgs().getUser());
Kenny Root05ca4c92011-09-15 10:36:25 -07001007 try {
1008 ret = args.copyApk(mContainerService, true);
1009 } catch (RemoteException e) {
1010 Slog.e(TAG, "Could not contact the ContainerService");
1011 }
1012 } else {
1013 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
Kenny Root5ab21572011-07-27 11:11:19 -07001014 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001015
1016 processPendingInstall(args, ret);
1017
1018 mHandler.sendEmptyMessage(MCS_UNBIND);
Kenny Root5ab21572011-07-27 11:11:19 -07001019 }
1020
Kenny Root5ab21572011-07-27 11:11:19 -07001021 break;
1022 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07001023 }
1024 }
1025 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08001026
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001027 void scheduleWriteSettingsLocked() {
1028 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
1029 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
1030 }
1031 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07001032
1033 void scheduleWritePackageRestrictionsLocked(int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001034 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -07001035 mDirtyUsers.add(userId);
1036 if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
1037 mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
Dianne Hackborne7f97212011-02-24 14:40:20 -08001038 }
1039 }
1040
Jeff Brownf69c8122012-09-12 17:00:34 -07001041 public static final IPackageManager main(Context context, Installer installer,
1042 boolean factoryTest, boolean onlyCore) {
1043 PackageManagerService m = new PackageManagerService(context, installer,
1044 factoryTest, onlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 ServiceManager.addService("package", m);
1046 return m;
1047 }
1048
1049 static String[] splitString(String str, char sep) {
1050 int count = 1;
1051 int i = 0;
1052 while ((i=str.indexOf(sep, i)) >= 0) {
1053 count++;
1054 i++;
1055 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 String[] res = new String[count];
1058 i=0;
1059 count = 0;
1060 int lastI=0;
1061 while ((i=str.indexOf(sep, i)) >= 0) {
1062 res[count] = str.substring(lastI, i);
1063 count++;
1064 i++;
1065 lastI = i;
1066 }
1067 res[count] = str.substring(lastI, str.length());
1068 return res;
1069 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001070
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08001071 private static void getDefaultDisplayMetrics(Context context, DisplayMetrics metrics) {
1072 DisplayManager displayManager = (DisplayManager) context.getSystemService(
1073 Context.DISPLAY_SERVICE);
1074 displayManager.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics);
1075 }
1076
Jeff Brownf69c8122012-09-12 17:00:34 -07001077 public PackageManagerService(Context context, Installer installer,
1078 boolean factoryTest, boolean onlyCore) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001079 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001083 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 mContext = context;
1087 mFactoryTest = factoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001088 mOnlyCore = onlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001089 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 mMetrics = new DisplayMetrics();
Amith Yamasani258848d2012-08-10 17:06:33 -07001091 mSettings = new Settings(context);
Christopher Tateccbf84f2013-05-08 15:25:41 -07001092 mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
1093 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1094 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
1095 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1096 mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
1097 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1098 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
1099 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1100 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
1101 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
1102 mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
1103 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104
1105 String separateProcesses = SystemProperties.get("debug.separate_processes");
1106 if (separateProcesses != null && separateProcesses.length() > 0) {
1107 if ("*".equals(separateProcesses)) {
1108 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
1109 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001110 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 } else {
1112 mDefParseFlags = 0;
1113 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001114 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 + separateProcesses);
1116 }
1117 } else {
1118 mDefParseFlags = 0;
1119 mSeparateProcesses = null;
1120 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001121
Jeff Brownf69c8122012-09-12 17:00:34 -07001122 mInstaller = installer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08001124 getDefaultDisplayMetrics(context, mMetrics);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125
1126 synchronized (mInstallLock) {
Kenny Root447106f2011-03-23 11:00:15 -07001127 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 synchronized (mPackages) {
Jeff Brown4ccb8232014-01-16 22:16:42 -08001129 mHandlerThread = new ServiceThread(TAG,
1130 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07001132 mHandler = new PackageHandler(mHandlerThread.getLooper());
Jeff Brown6f357d32014-01-15 20:40:55 -08001133 Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 File dataDir = Environment.getDataDirectory();
1136 mAppDataDir = new File(dataDir, "data");
Kenny Root584c4cd2012-10-29 10:46:42 -07001137 mAppInstallDir = new File(dataDir, "app");
1138 mAppLibInstallDir = new File(dataDir, "app-lib");
Kenny Root51a573c2012-05-17 13:30:28 -07001139 mAsecInternalPath = new File(dataDir, "app-asec").getPath();
Amith Yamasani0b285492011-04-14 17:35:23 -07001140 mUserAppDataDir = new File(dataDir, "user");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
1142
Dianne Hackborn4428e172012-08-24 17:43:05 -07001143 sUserManager = new UserManagerService(context, this,
1144 mInstallLock, mPackages);
Amith Yamasani0b285492011-04-14 17:35:23 -07001145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 readPermissions();
1147
Robert Craig0f40dc92013-03-25 06:33:03 -04001148 mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
1149
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08001150 mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false),
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001151 mSdkVersion, mOnlyCore);
Geremy Condraf1bcca82013-01-07 22:35:24 -08001152
Jose Limabb9682e2013-08-16 16:14:32 -07001153 String customResolverActivity = Resources.getSystem().getString(
1154 R.string.config_customResolverActivity);
1155 if (TextUtils.isEmpty(customResolverActivity)) {
1156 customResolverActivity = null;
1157 } else {
1158 mCustomResolverComponentName = ComponentName.unflattenFromString(
1159 customResolverActivity);
1160 }
1161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001163
1164 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001166
Suchi Amalapurapudaec1722010-01-14 21:25:16 -08001167 // Set flag to monitor and not change apk file paths when
1168 // scanning install directories.
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07001169 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001170 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001171 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001172 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001173 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001174
Brian Carlstromb33278f2013-08-01 13:55:07 -07001175 final HashSet<String> alreadyDexOpted = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001176
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001177 /**
Brian Carlstromb33278f2013-08-01 13:55:07 -07001178 * Add everything in the in the boot class path to the
1179 * list of process files because dexopt will have been run
1180 * if necessary during zygote startup.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001181 */
1182 String bootClassPath = System.getProperty("java.boot.class.path");
1183 if (bootClassPath != null) {
1184 String[] paths = splitString(bootClassPath, ':');
1185 for (int i=0; i<paths.length; i++) {
Brian Carlstromb33278f2013-08-01 13:55:07 -07001186 alreadyDexOpted.add(paths[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001188 } else {
1189 Slog.w(TAG, "No BOOTCLASSPATH found!");
1190 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001191
Brian Carlstromb33278f2013-08-01 13:55:07 -07001192 boolean didDexOpt = false;
1193
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001194 /**
Brian Carlstromb33278f2013-08-01 13:55:07 -07001195 * Ensure all external libraries have had dexopt run on them.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001196 */
1197 if (mSharedLibraries.size() > 0) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07001198 Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001199 while (libs.hasNext()) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07001200 String lib = libs.next().path;
1201 if (lib == null) {
1202 continue;
1203 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001204 try {
1205 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
Brian Carlstromb33278f2013-08-01 13:55:07 -07001206 alreadyDexOpted.add(lib);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001207 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
1208 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001210 } catch (FileNotFoundException e) {
1211 Slog.w(TAG, "Library not found: " + lib);
1212 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -07001213 Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
1214 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 }
1216 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001217 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001218
Brian Carlstromb33278f2013-08-01 13:55:07 -07001219 File frameworkDir = new File(Environment.getRootDirectory(), "framework");
1220
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001221 // Gross hack for now: we know this file doesn't contain any
1222 // code, so don't dexopt it to avoid the resulting log spew.
Brian Carlstromb33278f2013-08-01 13:55:07 -07001223 alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");
1224
1225 // Gross hack for now: we know this file is only part of
1226 // the boot class path for art, so don't dexopt it to
1227 // avoid the resulting log spew.
1228 alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001229
1230 /**
1231 * And there are a number of commands implemented in Java, which
1232 * we currently need to do the dexopt on so that they can be
1233 * run from a non-root shell.
1234 */
Brian Carlstromb33278f2013-08-01 13:55:07 -07001235 String[] frameworkFiles = frameworkDir.list();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001236 if (frameworkFiles != null) {
1237 for (int i=0; i<frameworkFiles.length; i++) {
Brian Carlstromb33278f2013-08-01 13:55:07 -07001238 File libPath = new File(frameworkDir, frameworkFiles[i]);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001239 String path = libPath.getPath();
1240 // Skip the file if we alrady did it.
Brian Carlstromb33278f2013-08-01 13:55:07 -07001241 if (alreadyDexOpted.contains(path)) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001242 continue;
1243 }
1244 // Skip the file if it is not a type we want to dexopt.
1245 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
1246 continue;
1247 }
1248 try {
1249 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
1250 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
1251 didDexOpt = true;
1252 }
1253 } catch (FileNotFoundException e) {
1254 Slog.w(TAG, "Jar not found: " + path);
1255 } catch (IOException e) {
1256 Slog.w(TAG, "Exception reading jar: " + path, e);
1257 }
1258 }
1259 }
1260
1261 if (didDexOpt) {
Brian Carlstromb33278f2013-08-01 13:55:07 -07001262 File dalvikCacheDir = new File(dataDir, "dalvik-cache");
1263
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001264 // If we had to do a dexopt of one of the previous
1265 // things, then something on the system has changed.
1266 // Consider this significant, and wipe away all other
1267 // existing dexopt files to ensure we don't leave any
1268 // dangling around.
Brian Carlstromb33278f2013-08-01 13:55:07 -07001269 String[] files = dalvikCacheDir.list();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001270 if (files != null) {
1271 for (int i=0; i<files.length; i++) {
1272 String fn = files[i];
1273 if (fn.startsWith("data@app@")
1274 || fn.startsWith("data@app-private@")) {
1275 Slog.i(TAG, "Pruning dalvik file: " + fn);
Brian Carlstromb33278f2013-08-01 13:55:07 -07001276 (new File(dalvikCacheDir, fn)).delete();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001277 }
1278 }
1279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001281
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001282 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 mFrameworkInstallObserver = new AppDirObserver(
Brian Carlstromb33278f2013-08-01 13:55:07 -07001284 frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 mFrameworkInstallObserver.startWatching();
Brian Carlstromb33278f2013-08-01 13:55:07 -07001286 scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
Christopher Tatecefba582013-11-14 18:10:35 -08001287 | PackageParser.PARSE_IS_SYSTEM_DIR
1288 | PackageParser.PARSE_IS_PRIVILEGED,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001289 scanMode | SCAN_NO_DEX, 0);
Kenny Root51a573c2012-05-17 13:30:28 -07001290
Christopher Tateccbf84f2013-05-08 15:25:41 -07001291 // Collected privileged system packages.
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001292 File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
Christopher Tateccbf84f2013-05-08 15:25:41 -07001293 mPrivilegedInstallObserver = new AppDirObserver(
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001294 privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true);
Christopher Tateccbf84f2013-05-08 15:25:41 -07001295 mPrivilegedInstallObserver.startWatching();
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001296 scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
Christopher Tateccbf84f2013-05-08 15:25:41 -07001297 | PackageParser.PARSE_IS_SYSTEM_DIR
1298 | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
1299
1300 // Collect ordinary system packages.
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001301 File systemAppDir = new File(Environment.getRootDirectory(), "app");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 mSystemInstallObserver = new AppDirObserver(
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001303 systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 mSystemInstallObserver.startWatching();
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001305 scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001306 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Kenny Root208d3412012-05-07 19:42:35 -07001307
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001308 // Collect all vendor packages.
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001309 File vendorAppDir = new File("/vendor/app");
Johan Redestig41a17c22014-01-30 09:39:00 +01001310 try {
1311 vendorAppDir = vendorAppDir.getCanonicalFile();
1312 } catch (IOException e) {
1313 // failed to look up canonical path, continue with original one
1314 }
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001315 mVendorInstallObserver = new AppDirObserver(
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001316 vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001317 mVendorInstallObserver.startWatching();
Brian Carlstromf4bdcab2013-08-02 19:49:15 -07001318 scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001319 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001320
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001321 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1322 mInstaller.moveFiles();
1323
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001324 // Prune any system packages that no longer exist.
Kenny Root87b5d7b2012-05-16 13:36:18 -07001325 final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001326 if (!mOnlyCore) {
1327 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1328 while (psit.hasNext()) {
1329 PackageSetting ps = psit.next();
Kenny Root208d3412012-05-07 19:42:35 -07001330
1331 /*
1332 * If this is not a system app, it can't be a
1333 * disable system app.
1334 */
1335 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1336 continue;
1337 }
1338
1339 /*
1340 * If the package is scanned, it's not erased.
1341 */
Kenny Rooteca64b32012-06-25 16:37:32 -07001342 final PackageParser.Package scannedPkg = mPackages.get(ps.name);
1343 if (scannedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07001344 /*
1345 * If the system app is both scanned and in the
1346 * disabled packages list, then it must have been
1347 * added via OTA. Remove it from the currently
1348 * scanned package so the previously user-installed
1349 * application can be scanned.
1350 */
1351 if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
Kenny Rooteca64b32012-06-25 16:37:32 -07001352 Slog.i(TAG, "Expecting better updatd system app for " + ps.name
1353 + "; removing system app");
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001354 removePackageLI(ps, true);
Kenny Root208d3412012-05-07 19:42:35 -07001355 }
1356
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001357 continue;
1358 }
1359
1360 if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001361 psit.remove();
1362 String msg = "System package " + ps.name
1363 + " no longer exists; wiping its data";
1364 reportSettingsProblem(Log.WARN, msg);
Dianne Hackborn4428e172012-08-24 17:43:05 -07001365 removeDataDirsLI(ps.name);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001366 } else {
Kenny Root87b5d7b2012-05-16 13:36:18 -07001367 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
1368 if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
1369 possiblyDeletedUpdatedSystemApps.add(ps.name);
1370 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001371 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001372 }
1373 }
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 //look for any incomplete package installations
Kenny Root447106f2011-03-23 11:00:15 -07001376 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 //clean up list
1378 for(int i = 0; i < deletePkgsList.size(); i++) {
1379 //clean up here
1380 cleanupInstallFailedPackage(deletePkgsList.get(i));
1381 }
1382 //delete tmp files
1383 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001384
Christopher Tate86b391c2013-09-13 16:58:36 -07001385 // Remove any shared userIDs that have no associated packages
1386 mSettings.pruneSharedUsersLPw();
1387
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001388 if (!mOnlyCore) {
1389 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1390 SystemClock.uptimeMillis());
1391 mAppInstallObserver = new AppDirObserver(
Christopher Tate409bb362013-07-12 12:29:41 -07001392 mAppInstallDir.getPath(), OBSERVER_EVENTS, false, false);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001393 mAppInstallObserver.startWatching();
1394 scanDirLI(mAppInstallDir, 0, scanMode, 0);
1395
1396 mDrmAppInstallObserver = new AppDirObserver(
Christopher Tate409bb362013-07-12 12:29:41 -07001397 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false, false);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001398 mDrmAppInstallObserver.startWatching();
1399 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1400 scanMode, 0);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001401
1402 /**
Kenny Root87b5d7b2012-05-16 13:36:18 -07001403 * Remove disable package settings for any updated system
1404 * apps that were removed via an OTA. If they're not a
1405 * previously-updated app, remove them completely.
1406 * Otherwise, just revoke their system-level permissions.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001407 */
Kenny Root87b5d7b2012-05-16 13:36:18 -07001408 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001409 PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
Kenny Root87b5d7b2012-05-16 13:36:18 -07001410 mSettings.removeDisabledSystemPackageLPw(deletedAppName);
1411
1412 String msg;
1413 if (deletedPkg == null) {
1414 msg = "Updated system package " + deletedAppName
1415 + " no longer exists; wiping its data";
Dianne Hackborn4428e172012-08-24 17:43:05 -07001416 removeDataDirsLI(deletedAppName);
Kenny Root87b5d7b2012-05-16 13:36:18 -07001417 } else {
1418 msg = "Updated system app + " + deletedAppName
1419 + " no longer present; removing system privileges for "
1420 + deletedAppName;
1421
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001422 deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
1423
1424 PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
1425 deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
1426 }
Kenny Root87b5d7b2012-05-16 13:36:18 -07001427 reportSettingsProblem(Log.WARN, msg);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001428 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001429 } else {
1430 mAppInstallObserver = null;
1431 mDrmAppInstallObserver = null;
1432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433
Dianne Hackbornc895be72013-03-11 17:48:43 -07001434 // Now that we know all of the shared libraries, update all clients to have
1435 // the correct library paths.
1436 updateAllSharedLibrariesLPw();
1437
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001438 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001440 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1442 + " seconds");
1443
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001444 // If the platform SDK has changed since the last time we booted,
1445 // we need to re-grant app permission to catch any new ones that
1446 // appear. This is really a hack, and means that apps can in some
1447 // cases get permissions that the user didn't initially explicitly
1448 // allow... it would be nice to have some better way to handle
1449 // this situation.
1450 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1451 != mSdkVersion;
1452 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1453 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1454 + "; regranting permissions for internal storage");
1455 mSettings.mInternalSdkPlatform = mSdkVersion;
1456
Dianne Hackborne639da72012-02-21 15:11:13 -08001457 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
1458 | (regrantPermissions
1459 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
1460 : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461
Dianne Hackborn4d491a62013-04-01 18:10:51 -07001462 // If this is the first boot, and it is a normal boot, then
1463 // we need to initialize the default preferred apps.
1464 if (!mRestoredSettings && !onlyCore) {
1465 mSettings.readDefaultPreferredAppsLPw(this, 0);
1466 }
1467
Kenny Root447106f2011-03-23 11:00:15 -07001468 // can downgrade to reader
1469 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001471 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 // Now after opening every single application zip, make sure they
1475 // are all flushed. Not really needed, but keeps things nice and
1476 // tidy.
1477 Runtime.getRuntime().gc();
Kenny Root05ca4c92011-09-15 10:36:25 -07001478
1479 mRequiredVerifierPackage = getRequiredVerifierLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 } // synchronized (mPackages)
1481 } // synchronized (mInstallLock)
1482 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001483
Dianne Hackborn58f42a52011-10-10 13:46:34 -07001484 public boolean isFirstBoot() {
1485 return !mRestoredSettings;
1486 }
1487
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001488 public boolean isOnlyCoreApps() {
1489 return mOnlyCore;
1490 }
1491
Kenny Root05ca4c92011-09-15 10:36:25 -07001492 private String getRequiredVerifierLPr() {
1493 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1494 final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
Amith Yamasani483f3b02012-03-13 16:08:00 -07001495 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07001496
1497 String requiredVerifier = null;
1498
1499 final int N = receivers.size();
1500 for (int i = 0; i < N; i++) {
1501 final ResolveInfo info = receivers.get(i);
1502
1503 if (info.activityInfo == null) {
1504 continue;
1505 }
1506
1507 final String packageName = info.activityInfo.packageName;
1508
1509 final PackageSetting ps = mSettings.mPackages.get(packageName);
1510 if (ps == null) {
1511 continue;
1512 }
1513
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001514 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1515 if (!gp.grantedPermissions
Kenny Root05ca4c92011-09-15 10:36:25 -07001516 .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
1517 continue;
1518 }
1519
1520 if (requiredVerifier != null) {
1521 throw new RuntimeException("There can be only one required verifier");
1522 }
1523
1524 requiredVerifier = packageName;
1525 }
1526
1527 return requiredVerifier;
1528 }
1529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 @Override
1531 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1532 throws RemoteException {
1533 try {
1534 return super.onTransact(code, data, reply, flags);
1535 } catch (RuntimeException e) {
1536 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001537 Slog.wtf(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 }
1539 throw e;
1540 }
1541 }
1542
Dianne Hackborne6620b22010-01-22 14:46:21 -08001543 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001544 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
Dianne Hackborn4428e172012-08-24 17:43:05 -07001545 removeDataDirsLI(ps.name);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001546 if (ps.codePath != null) {
1547 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001548 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001549 }
1550 }
1551 if (ps.resourcePath != null) {
1552 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001553 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001554 }
1555 }
Kenny Root447106f2011-03-23 11:00:15 -07001556 mSettings.removePackageLPw(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 }
1558
1559 void readPermissions() {
1560 // Read permissions from .../etc/permission directory.
1561 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1562 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001563 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 return;
1565 }
1566 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001567 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 return;
1569 }
1570
1571 // Iterate over the files in the directory and scan .xml files
1572 for (File f : libraryDir.listFiles()) {
1573 // We'll read platform.xml last
1574 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1575 continue;
1576 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001579 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 continue;
1581 }
1582 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001583 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 continue;
1585 }
1586
1587 readPermissionsFromXml(f);
1588 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1591 final File permFile = new File(Environment.getRootDirectory(),
1592 "etc/permissions/platform.xml");
1593 readPermissionsFromXml(permFile);
1594 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001595
1596 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 FileReader permReader = null;
1598 try {
1599 permReader = new FileReader(permFile);
1600 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001601 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 return;
1603 }
1604
1605 try {
1606 XmlPullParser parser = Xml.newPullParser();
1607 parser.setInput(permReader);
1608
1609 XmlUtils.beginDocument(parser, "permissions");
1610
1611 while (true) {
1612 XmlUtils.nextElement(parser);
1613 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1614 break;
1615 }
1616
1617 String name = parser.getName();
1618 if ("group".equals(name)) {
1619 String gidStr = parser.getAttributeValue(null, "gid");
1620 if (gidStr != null) {
Romain Guy01d159d2013-02-25 13:22:42 -08001621 int gid = Process.getGidForName(gidStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 mGlobalGids = appendInt(mGlobalGids, gid);
1623 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001624 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 + parser.getPositionDescription());
1626 }
1627
1628 XmlUtils.skipCurrentTag(parser);
1629 continue;
1630 } else if ("permission".equals(name)) {
1631 String perm = parser.getAttributeValue(null, "name");
1632 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001633 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 + parser.getPositionDescription());
1635 XmlUtils.skipCurrentTag(parser);
1636 continue;
1637 }
1638 perm = perm.intern();
1639 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 } else if ("assign-permission".equals(name)) {
1642 String perm = parser.getAttributeValue(null, "name");
1643 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001644 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 + parser.getPositionDescription());
1646 XmlUtils.skipCurrentTag(parser);
1647 continue;
1648 }
1649 String uidStr = parser.getAttributeValue(null, "uid");
1650 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001651 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 + parser.getPositionDescription());
1653 XmlUtils.skipCurrentTag(parser);
1654 continue;
1655 }
1656 int uid = Process.getUidForName(uidStr);
1657 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001658 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 + uidStr + "\" at "
1660 + parser.getPositionDescription());
1661 XmlUtils.skipCurrentTag(parser);
1662 continue;
1663 }
1664 perm = perm.intern();
1665 HashSet<String> perms = mSystemPermissions.get(uid);
1666 if (perms == null) {
1667 perms = new HashSet<String>();
1668 mSystemPermissions.put(uid, perms);
1669 }
1670 perms.add(perm);
1671 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 } else if ("library".equals(name)) {
1674 String lname = parser.getAttributeValue(null, "name");
1675 String lfile = parser.getAttributeValue(null, "file");
1676 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001677 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 + parser.getPositionDescription());
1679 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001680 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 + parser.getPositionDescription());
1682 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001683 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackbornc895be72013-03-11 17:48:43 -07001684 mSharedLibraries.put(lname, new SharedLibraryEntry(lfile, null));
Dianne Hackborn49237342009-08-27 20:08:01 -07001685 }
1686 XmlUtils.skipCurrentTag(parser);
1687 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001688
Dianne Hackborn49237342009-08-27 20:08:01 -07001689 } else if ("feature".equals(name)) {
1690 String fname = parser.getAttributeValue(null, "name");
1691 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001692 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001693 + parser.getPositionDescription());
1694 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001695 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001696 FeatureInfo fi = new FeatureInfo();
1697 fi.name = fname;
1698 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
1700 XmlUtils.skipCurrentTag(parser);
1701 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 } else {
1704 XmlUtils.skipCurrentTag(parser);
1705 continue;
1706 }
1707
1708 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001709 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001711 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001713 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 }
1715 }
1716
1717 void readPermission(XmlPullParser parser, String name)
1718 throws IOException, XmlPullParserException {
1719
1720 name = name.intern();
1721
1722 BasePermission bp = mSettings.mPermissions.get(name);
1723 if (bp == null) {
1724 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1725 mSettings.mPermissions.put(name, bp);
1726 }
1727 int outerDepth = parser.getDepth();
1728 int type;
1729 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1730 && (type != XmlPullParser.END_TAG
1731 || parser.getDepth() > outerDepth)) {
1732 if (type == XmlPullParser.END_TAG
1733 || type == XmlPullParser.TEXT) {
1734 continue;
1735 }
1736
1737 String tagName = parser.getName();
1738 if ("group".equals(tagName)) {
1739 String gidStr = parser.getAttributeValue(null, "gid");
1740 if (gidStr != null) {
1741 int gid = Process.getGidForName(gidStr);
1742 bp.gids = appendInt(bp.gids, gid);
1743 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001744 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 + parser.getPositionDescription());
1746 }
1747 }
1748 XmlUtils.skipCurrentTag(parser);
1749 }
1750 }
1751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 static int[] appendInts(int[] cur, int[] add) {
1753 if (add == null) return cur;
1754 if (cur == null) return add;
1755 final int N = add.length;
1756 for (int i=0; i<N; i++) {
1757 cur = appendInt(cur, add[i]);
1758 }
1759 return cur;
1760 }
1761
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001762 static int[] removeInts(int[] cur, int[] rem) {
1763 if (rem == null) return cur;
1764 if (cur == null) return cur;
1765 final int N = rem.length;
1766 for (int i=0; i<N; i++) {
1767 cur = removeInt(cur, rem[i]);
1768 }
1769 return cur;
1770 }
1771
Amith Yamasani13593602012-03-22 16:16:17 -07001772 PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
1773 if (!sUserManager.exists(userId)) return null;
1774 PackageInfo pi;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001775 final PackageSetting ps = (PackageSetting) p.mExtras;
1776 if (ps == null) {
1777 return null;
1778 }
1779 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1780 final PackageUserState state = ps.readUserState(userId);
Jeff Sharkey94d7ddb2013-03-06 15:02:12 -08001781 return PackageParser.generatePackageInfo(p, gp.gids, flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001782 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
1783 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 }
1785
Christopher Tateba629da2013-11-13 17:42:28 -08001786 public boolean isPackageAvailable(String packageName, int userId) {
1787 if (!sUserManager.exists(userId)) return false;
1788 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "is package available");
1789 synchronized (mPackages) {
1790 PackageParser.Package p = mPackages.get(packageName);
1791 if (p != null) {
1792 final PackageSetting ps = (PackageSetting) p.mExtras;
1793 if (ps != null) {
1794 final PackageUserState state = ps.readUserState(userId);
1795 if (state != null) {
1796 return PackageParser.isAvailable(state);
1797 }
1798 }
1799 }
1800 }
1801 return false;
1802 }
1803
Amith Yamasani483f3b02012-03-13 16:08:00 -07001804 @Override
1805 public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001806 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001807 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package info");
Kenny Root447106f2011-03-23 11:00:15 -07001808 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 synchronized (mPackages) {
1810 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001811 if (DEBUG_PACKAGE_INFO)
1812 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001814 return generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 }
1816 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001817 return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 }
1819 }
1820 return null;
1821 }
1822
Dianne Hackborn47096932010-02-11 15:57:09 -08001823 public String[] currentToCanonicalPackageNames(String[] names) {
1824 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001825 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001826 synchronized (mPackages) {
1827 for (int i=names.length-1; i>=0; i--) {
1828 PackageSetting ps = mSettings.mPackages.get(names[i]);
1829 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1830 }
1831 }
1832 return out;
1833 }
1834
1835 public String[] canonicalToCurrentPackageNames(String[] names) {
1836 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001837 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001838 synchronized (mPackages) {
1839 for (int i=names.length-1; i>=0; i--) {
1840 String cur = mSettings.mRenamedPackages.get(names[i]);
1841 out[i] = cur != null ? cur : names[i];
1842 }
1843 }
1844 return out;
1845 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07001846
1847 @Override
1848 public int getPackageUid(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001849 if (!sUserManager.exists(userId)) return -1;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001850 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package uid");
Kenny Root447106f2011-03-23 11:00:15 -07001851 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 synchronized (mPackages) {
1853 PackageParser.Package p = mPackages.get(packageName);
1854 if(p != null) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001855 return UserHandle.getUid(userId, p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857 PackageSetting ps = mSettings.mPackages.get(packageName);
1858 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1859 return -1;
1860 }
1861 p = ps.pkg;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001862 return p != null ? UserHandle.getUid(userId, p.applicationInfo.uid) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 }
1864 }
1865
Jeff Sharkey02e4d16e2013-08-12 20:31:36 -07001866 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 public int[] getPackageGids(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07001868 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 synchronized (mPackages) {
1870 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001871 if (DEBUG_PACKAGE_INFO)
1872 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 if (p != null) {
1874 final PackageSetting ps = (PackageSetting)p.mExtras;
Jeff Sharkey02e4d16e2013-08-12 20:31:36 -07001875 return ps.getGids();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 }
1877 }
1878 // stupid thing to indicate an error.
1879 return new int[0];
1880 }
1881
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001882 static final PermissionInfo generatePermissionInfo(
1883 BasePermission bp, int flags) {
1884 if (bp.perm != null) {
1885 return PackageParser.generatePermissionInfo(bp.perm, flags);
1886 }
1887 PermissionInfo pi = new PermissionInfo();
1888 pi.name = bp.name;
1889 pi.packageName = bp.sourcePackage;
1890 pi.nonLocalizedLabel = bp.name;
1891 pi.protectionLevel = bp.protectionLevel;
1892 return pi;
1893 }
1894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 public PermissionInfo getPermissionInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001896 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 synchronized (mPackages) {
1898 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001899 if (p != null) {
1900 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 }
1902 return null;
1903 }
1904 }
1905
1906 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001907 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 synchronized (mPackages) {
1909 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1910 for (BasePermission p : mSettings.mPermissions.values()) {
1911 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001912 if (p.perm == null || p.perm.info.group == null) {
1913 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 }
1915 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001916 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1918 }
1919 }
1920 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 if (out.size() > 0) {
1923 return out;
1924 }
1925 return mPermissionGroups.containsKey(group) ? out : null;
1926 }
1927 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001930 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 synchronized (mPackages) {
1932 return PackageParser.generatePermissionGroupInfo(
1933 mPermissionGroups.get(name), flags);
1934 }
1935 }
1936
1937 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001938 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 synchronized (mPackages) {
1940 final int N = mPermissionGroups.size();
1941 ArrayList<PermissionGroupInfo> out
1942 = new ArrayList<PermissionGroupInfo>(N);
1943 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1944 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1945 }
1946 return out;
1947 }
1948 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001949
Amith Yamasani483f3b02012-03-13 16:08:00 -07001950 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
1951 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001952 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001954 if (ps != null) {
1955 if (ps.pkg == null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001956 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName,
1957 flags, userId);
Kenny Root447106f2011-03-23 11:00:15 -07001958 if (pInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 return pInfo.applicationInfo;
1960 }
1961 return null;
1962 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001963 return PackageParser.generateApplicationInfo(ps.pkg, flags,
1964 ps.readUserState(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 }
1966 return null;
1967 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001968
Amith Yamasani483f3b02012-03-13 16:08:00 -07001969 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
1970 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001971 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001973 if (ps != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001974 PackageParser.Package pkg = ps.pkg;
1975 if (pkg == null) {
1976 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
1977 return null;
1978 }
1979 pkg = new PackageParser.Package(packageName);
1980 pkg.applicationInfo.packageName = packageName;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001981 pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001982 pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1983 pkg.applicationInfo.sourceDir = ps.codePathString;
1984 pkg.applicationInfo.dataDir =
Amith Yamasani317046a2012-08-29 18:48:08 -07001985 getDataPathForPackage(packageName, 0).getPath();
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001986 pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001987 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001988 return generatePackageInfo(pkg, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 }
1990 return null;
1991 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001992
Amith Yamasani483f3b02012-03-13 16:08:00 -07001993 @Override
1994 public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001995 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001996 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get application info");
Kenny Root447106f2011-03-23 11:00:15 -07001997 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 synchronized (mPackages) {
1999 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08002000 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 TAG, "getApplicationInfo " + packageName
2002 + ": " + p);
2003 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07002004 PackageSetting ps = mSettings.mPackages.get(packageName);
2005 if (ps == null) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 // Note: isEnabledLP() does not apply here - always return info
Jeff Sharkey38f86882012-10-11 16:10:23 -07002007 return PackageParser.generateApplicationInfo(
2008 p, flags, ps.readUserState(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 }
2010 if ("android".equals(packageName)||"system".equals(packageName)) {
2011 return mAndroidApplication;
2012 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07002013 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002014 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 }
2016 }
2017 return null;
2018 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002019
2020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
2022 mContext.enforceCallingOrSelfPermission(
2023 android.Manifest.permission.CLEAR_APP_CACHE, null);
2024 // Queue up an async operation since clearing cache may take a little while.
2025 mHandler.post(new Runnable() {
2026 public void run() {
2027 mHandler.removeCallbacks(this);
2028 int retCode = -1;
Dianne Hackborn4428e172012-08-24 17:43:05 -07002029 synchronized (mInstallLock) {
2030 retCode = mInstaller.freeCache(freeStorageSize);
2031 if (retCode < 0) {
2032 Slog.w(TAG, "Couldn't clear application caches");
2033 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07002034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 if (observer != null) {
2036 try {
2037 observer.onRemoveCompleted(null, (retCode >= 0));
2038 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002039 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 }
2041 }
2042 }
2043 });
2044 }
2045
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002046 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002047 mContext.enforceCallingOrSelfPermission(
2048 android.Manifest.permission.CLEAR_APP_CACHE, null);
2049 // Queue up an async operation since clearing cache may take a little while.
2050 mHandler.post(new Runnable() {
2051 public void run() {
2052 mHandler.removeCallbacks(this);
2053 int retCode = -1;
Dianne Hackborn4428e172012-08-24 17:43:05 -07002054 synchronized (mInstallLock) {
2055 retCode = mInstaller.freeCache(freeStorageSize);
2056 if (retCode < 0) {
2057 Slog.w(TAG, "Couldn't clear application caches");
2058 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002059 }
2060 if(pi != null) {
2061 try {
2062 // Callback via pending intent
2063 int code = (retCode >= 0) ? 1 : 0;
2064 pi.sendIntent(null, code, null,
2065 null, null);
2066 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002067 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002068 }
2069 }
2070 }
2071 });
2072 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002073
Amith Yamasani483f3b02012-03-13 16:08:00 -07002074 @Override
2075 public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002076 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07002077 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get activity info");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 synchronized (mPackages) {
2079 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07002080
Kenny Root9718cf52011-02-23 16:45:26 -08002081 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002082 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07002083 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2084 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07002085 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
2086 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002087 }
2088 if (mResolveComponentName.equals(component)) {
2089 return mResolveActivity;
2090 }
2091 }
2092 return null;
2093 }
2094
Amith Yamasani483f3b02012-03-13 16:08:00 -07002095 @Override
2096 public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002097 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07002098 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get receiver info");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 synchronized (mPackages) {
2100 PackageParser.Activity a = mReceivers.mActivities.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08002101 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 TAG, "getReceiverInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002103 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07002104 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2105 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07002106 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
2107 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 }
2109 }
2110 return null;
2111 }
2112
Amith Yamasani483f3b02012-03-13 16:08:00 -07002113 @Override
2114 public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002115 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07002116 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get service info");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 synchronized (mPackages) {
2118 PackageParser.Service s = mServices.mServices.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08002119 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 TAG, "getServiceInfo " + component + ": " + s);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002121 if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07002122 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2123 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07002124 return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
2125 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 }
2127 }
2128 return null;
2129 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002130
Amith Yamasani483f3b02012-03-13 16:08:00 -07002131 @Override
2132 public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002133 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07002134 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info");
Dianne Hackborn361199b2010-08-30 17:42:07 -07002135 synchronized (mPackages) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07002136 PackageParser.Provider p = mProviders.mProviders.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08002137 if (DEBUG_PACKAGE_INFO) Log.v(
Dianne Hackborn361199b2010-08-30 17:42:07 -07002138 TAG, "getProviderInfo " + component + ": " + p);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002139 if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07002140 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
2141 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07002142 return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
2143 userId);
Dianne Hackborn361199b2010-08-30 17:42:07 -07002144 }
2145 }
2146 return null;
2147 }
2148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 public String[] getSystemSharedLibraryNames() {
2150 Set<String> libSet;
2151 synchronized (mPackages) {
2152 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07002153 int size = libSet.size();
2154 if (size > 0) {
2155 String[] libs = new String[size];
2156 libSet.toArray(libs);
2157 return libs;
2158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002160 return null;
2161 }
2162
2163 public FeatureInfo[] getSystemAvailableFeatures() {
2164 Collection<FeatureInfo> featSet;
2165 synchronized (mPackages) {
2166 featSet = mAvailableFeatures.values();
2167 int size = featSet.size();
2168 if (size > 0) {
2169 FeatureInfo[] features = new FeatureInfo[size+1];
2170 featSet.toArray(features);
2171 FeatureInfo fi = new FeatureInfo();
2172 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
2173 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2174 features[size] = fi;
2175 return features;
2176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 }
2178 return null;
2179 }
2180
Dianne Hackborn039c68e2009-09-26 16:39:23 -07002181 public boolean hasSystemFeature(String name) {
2182 synchronized (mPackages) {
2183 return mAvailableFeatures.containsKey(name);
2184 }
2185 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002186
Amith Yamasani483f3b02012-03-13 16:08:00 -07002187 private void checkValidCaller(int uid, int userId) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002188 if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
Amith Yamasani483f3b02012-03-13 16:08:00 -07002189 return;
2190
2191 throw new SecurityException("Caller uid=" + uid
2192 + " is not privileged to communicate with user=" + userId);
2193 }
2194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 public int checkPermission(String permName, String pkgName) {
2196 synchronized (mPackages) {
2197 PackageParser.Package p = mPackages.get(pkgName);
2198 if (p != null && p.mExtras != null) {
2199 PackageSetting ps = (PackageSetting)p.mExtras;
2200 if (ps.sharedUser != null) {
2201 if (ps.sharedUser.grantedPermissions.contains(permName)) {
2202 return PackageManager.PERMISSION_GRANTED;
2203 }
2204 } else if (ps.grantedPermissions.contains(permName)) {
2205 return PackageManager.PERMISSION_GRANTED;
2206 }
2207 }
2208 }
2209 return PackageManager.PERMISSION_DENIED;
2210 }
2211
2212 public int checkUidPermission(String permName, int uid) {
2213 synchronized (mPackages) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002214 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002216 GrantedPermissions gp = (GrantedPermissions)obj;
2217 if (gp.grantedPermissions.contains(permName)) {
2218 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219 }
2220 } else {
2221 HashSet<String> perms = mSystemPermissions.get(uid);
2222 if (perms != null && perms.contains(permName)) {
2223 return PackageManager.PERMISSION_GRANTED;
2224 }
2225 }
2226 }
2227 return PackageManager.PERMISSION_DENIED;
2228 }
2229
Amith Yamasanif203aee2012-08-29 18:41:53 -07002230 /**
2231 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
2232 * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
2233 * @param message the message to log on security exception
2234 * @return
2235 */
2236 private void enforceCrossUserPermission(int callingUid, int userId,
2237 boolean requireFullPermission, String message) {
2238 if (userId < 0) {
2239 throw new IllegalArgumentException("Invalid userId " + userId);
2240 }
2241 if (userId == UserHandle.getUserId(callingUid)) return;
2242 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
2243 if (requireFullPermission) {
2244 mContext.enforceCallingOrSelfPermission(
2245 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
2246 } else {
2247 try {
2248 mContext.enforceCallingOrSelfPermission(
2249 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
2250 } catch (SecurityException se) {
2251 mContext.enforceCallingOrSelfPermission(
2252 android.Manifest.permission.INTERACT_ACROSS_USERS, message);
2253 }
2254 }
2255 }
2256 }
2257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 private BasePermission findPermissionTreeLP(String permName) {
2259 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
2260 if (permName.startsWith(bp.name) &&
2261 permName.length() > bp.name.length() &&
2262 permName.charAt(bp.name.length()) == '.') {
2263 return bp;
2264 }
2265 }
2266 return null;
2267 }
2268
2269 private BasePermission checkPermissionTreeLP(String permName) {
2270 if (permName != null) {
2271 BasePermission bp = findPermissionTreeLP(permName);
2272 if (bp != null) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002273 if (bp.uid == UserHandle.getAppId(Binder.getCallingUid())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 return bp;
2275 }
2276 throw new SecurityException("Calling uid "
2277 + Binder.getCallingUid()
2278 + " is not allowed to add to permission tree "
2279 + bp.name + " owned by uid " + bp.uid);
2280 }
2281 }
2282 throw new SecurityException("No permission tree found for " + permName);
2283 }
2284
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002285 static boolean compareStrings(CharSequence s1, CharSequence s2) {
2286 if (s1 == null) {
2287 return s2 == null;
2288 }
2289 if (s2 == null) {
2290 return false;
2291 }
2292 if (s1.getClass() != s2.getClass()) {
2293 return false;
2294 }
2295 return s1.equals(s2);
2296 }
2297
2298 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
2299 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07002300 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002301 if (pi1.protectionLevel != pi2.protectionLevel) return false;
2302 if (!compareStrings(pi1.name, pi2.name)) return false;
2303 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
2304 // We'll take care of setting this one.
2305 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
2306 // These are not currently stored in settings.
2307 //if (!compareStrings(pi1.group, pi2.group)) return false;
2308 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
2309 //if (pi1.labelRes != pi2.labelRes) return false;
2310 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
2311 return true;
2312 }
2313
2314 boolean addPermissionLocked(PermissionInfo info, boolean async) {
2315 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
2316 throw new SecurityException("Label must be specified in permission");
2317 }
2318 BasePermission tree = checkPermissionTreeLP(info.name);
2319 BasePermission bp = mSettings.mPermissions.get(info.name);
2320 boolean added = bp == null;
2321 boolean changed = true;
Dianne Hackborne639da72012-02-21 15:11:13 -08002322 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002323 if (added) {
2324 bp = new BasePermission(info.name, tree.sourcePackage,
2325 BasePermission.TYPE_DYNAMIC);
2326 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
2327 throw new SecurityException(
2328 "Not allowed to modify non-dynamic permission "
2329 + info.name);
2330 } else {
Dianne Hackborne639da72012-02-21 15:11:13 -08002331 if (bp.protectionLevel == fixedLevel
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002332 && bp.perm.owner.equals(tree.perm.owner)
2333 && bp.uid == tree.uid
2334 && comparePermissionInfos(bp.perm.info, info)) {
2335 changed = false;
2336 }
2337 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002338 bp.protectionLevel = fixedLevel;
2339 info = new PermissionInfo(info);
2340 info.protectionLevel = fixedLevel;
2341 bp.perm = new PackageParser.Permission(tree.perm.owner, info);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002342 bp.perm.info.packageName = tree.perm.info.packageName;
2343 bp.uid = tree.uid;
2344 if (added) {
2345 mSettings.mPermissions.put(info.name, bp);
2346 }
2347 if (changed) {
2348 if (!async) {
Kenny Root447106f2011-03-23 11:00:15 -07002349 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002350 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002351 scheduleWriteSettingsLocked();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002352 }
2353 }
2354 return added;
2355 }
2356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 public boolean addPermission(PermissionInfo info) {
2358 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002359 return addPermissionLocked(info, false);
2360 }
2361 }
2362
2363 public boolean addPermissionAsync(PermissionInfo info) {
2364 synchronized (mPackages) {
2365 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 }
2367 }
2368
2369 public void removePermission(String name) {
2370 synchronized (mPackages) {
2371 checkPermissionTreeLP(name);
2372 BasePermission bp = mSettings.mPermissions.get(name);
2373 if (bp != null) {
2374 if (bp.type != BasePermission.TYPE_DYNAMIC) {
2375 throw new SecurityException(
2376 "Not allowed to modify non-dynamic permission "
2377 + name);
2378 }
2379 mSettings.mPermissions.remove(name);
Kenny Root447106f2011-03-23 11:00:15 -07002380 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 }
2382 }
2383 }
2384
Nick Kralevichc4986142013-03-24 14:27:17 -07002385 private static void checkGrantRevokePermissions(PackageParser.Package pkg, BasePermission bp) {
2386 int index = pkg.requestedPermissions.indexOf(bp.name);
2387 if (index == -1) {
2388 throw new SecurityException("Package " + pkg.packageName
2389 + " has not requested permission " + bp.name);
2390 }
2391 boolean isNormal =
2392 ((bp.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE)
2393 == PermissionInfo.PROTECTION_NORMAL);
2394 boolean isDangerous =
2395 ((bp.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE)
2396 == PermissionInfo.PROTECTION_DANGEROUS);
2397 boolean isDevelopment =
2398 ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
2399
2400 if (!isNormal && !isDangerous && !isDevelopment) {
2401 throw new SecurityException("Permission " + bp.name
2402 + " is not a changeable permission type");
2403 }
2404
2405 if (isNormal || isDangerous) {
2406 if (pkg.requestedPermissionsRequired.get(index)) {
2407 throw new SecurityException("Can't change " + bp.name
2408 + ". It is required by the application");
2409 }
2410 }
2411 }
2412
Dianne Hackborne639da72012-02-21 15:11:13 -08002413 public void grantPermission(String packageName, String permissionName) {
2414 mContext.enforceCallingOrSelfPermission(
2415 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2416 synchronized (mPackages) {
2417 final PackageParser.Package pkg = mPackages.get(packageName);
2418 if (pkg == null) {
2419 throw new IllegalArgumentException("Unknown package: " + packageName);
2420 }
2421 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2422 if (bp == null) {
Nick Kralevichc4986142013-03-24 14:27:17 -07002423 throw new IllegalArgumentException("Unknown permission: " + permissionName);
Dianne Hackborne639da72012-02-21 15:11:13 -08002424 }
Nick Kralevichc4986142013-03-24 14:27:17 -07002425
2426 checkGrantRevokePermissions(pkg, bp);
2427
Dianne Hackborne639da72012-02-21 15:11:13 -08002428 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2429 if (ps == null) {
2430 return;
2431 }
Nick Kralevichc4986142013-03-24 14:27:17 -07002432 final GrantedPermissions gp = (ps.sharedUser != null) ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08002433 if (gp.grantedPermissions.add(permissionName)) {
2434 if (ps.haveGids) {
2435 gp.gids = appendInts(gp.gids, bp.gids);
2436 }
2437 mSettings.writeLPr();
2438 }
2439 }
2440 }
2441
2442 public void revokePermission(String packageName, String permissionName) {
Dianne Hackbornf1b78242013-04-08 22:28:59 -07002443 int changedAppId = -1;
2444
Dianne Hackborne639da72012-02-21 15:11:13 -08002445 synchronized (mPackages) {
2446 final PackageParser.Package pkg = mPackages.get(packageName);
2447 if (pkg == null) {
2448 throw new IllegalArgumentException("Unknown package: " + packageName);
2449 }
2450 if (pkg.applicationInfo.uid != Binder.getCallingUid()) {
2451 mContext.enforceCallingOrSelfPermission(
2452 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2453 }
2454 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2455 if (bp == null) {
Nick Kralevichc4986142013-03-24 14:27:17 -07002456 throw new IllegalArgumentException("Unknown permission: " + permissionName);
Dianne Hackborne639da72012-02-21 15:11:13 -08002457 }
Nick Kralevichc4986142013-03-24 14:27:17 -07002458
2459 checkGrantRevokePermissions(pkg, bp);
2460
Dianne Hackborne639da72012-02-21 15:11:13 -08002461 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2462 if (ps == null) {
2463 return;
2464 }
Nick Kralevichc4986142013-03-24 14:27:17 -07002465 final GrantedPermissions gp = (ps.sharedUser != null) ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08002466 if (gp.grantedPermissions.remove(permissionName)) {
2467 gp.grantedPermissions.remove(permissionName);
2468 if (ps.haveGids) {
2469 gp.gids = removeInts(gp.gids, bp.gids);
2470 }
2471 mSettings.writeLPr();
Dianne Hackbornf1b78242013-04-08 22:28:59 -07002472 changedAppId = ps.appId;
2473 }
2474 }
2475
2476 if (changedAppId >= 0) {
2477 // We changed the perm on someone, kill its processes.
2478 IActivityManager am = ActivityManagerNative.getDefault();
2479 if (am != null) {
2480 final int callingUserId = UserHandle.getCallingUserId();
2481 final long ident = Binder.clearCallingIdentity();
2482 try {
2483 //XXX we should only revoke for the calling user's app permissions,
2484 // but for now we impact all users.
2485 //am.killUid(UserHandle.getUid(callingUserId, changedAppId),
2486 // "revoke " + permissionName);
2487 int[] users = sUserManager.getUserIds();
2488 for (int user : users) {
2489 am.killUid(UserHandle.getUid(user, changedAppId),
2490 "revoke " + permissionName);
2491 }
2492 } catch (RemoteException e) {
2493 } finally {
2494 Binder.restoreCallingIdentity(ident);
2495 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002496 }
2497 }
2498 }
2499
Dianne Hackborn854060af2009-07-09 18:14:31 -07002500 public boolean isProtectedBroadcast(String actionName) {
2501 synchronized (mPackages) {
2502 return mProtectedBroadcasts.contains(actionName);
2503 }
2504 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 public int checkSignatures(String pkg1, String pkg2) {
2507 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002508 final PackageParser.Package p1 = mPackages.get(pkg1);
2509 final PackageParser.Package p2 = mPackages.get(pkg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 if (p1 == null || p1.mExtras == null
2511 || p2 == null || p2.mExtras == null) {
2512 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2513 }
Kenny Root447106f2011-03-23 11:00:15 -07002514 return compareSignatures(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 }
2516 }
2517
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002518 public int checkUidSignatures(int uid1, int uid2) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002519 // Map to base uids.
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002520 uid1 = UserHandle.getAppId(uid1);
2521 uid2 = UserHandle.getAppId(uid2);
Kenny Root447106f2011-03-23 11:00:15 -07002522 // reader
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002523 synchronized (mPackages) {
2524 Signature[] s1;
2525 Signature[] s2;
Kenny Root447106f2011-03-23 11:00:15 -07002526 Object obj = mSettings.getUserIdLPr(uid1);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002527 if (obj != null) {
2528 if (obj instanceof SharedUserSetting) {
2529 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
2530 } else if (obj instanceof PackageSetting) {
2531 s1 = ((PackageSetting)obj).signatures.mSignatures;
2532 } else {
2533 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2534 }
2535 } else {
2536 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2537 }
Kenny Root447106f2011-03-23 11:00:15 -07002538 obj = mSettings.getUserIdLPr(uid2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002539 if (obj != null) {
2540 if (obj instanceof SharedUserSetting) {
2541 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
2542 } else if (obj instanceof PackageSetting) {
2543 s2 = ((PackageSetting)obj).signatures.mSignatures;
2544 } else {
2545 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2546 }
2547 } else {
2548 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2549 }
Kenny Root447106f2011-03-23 11:00:15 -07002550 return compareSignatures(s1, s2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002551 }
2552 }
2553
Kenny Root447106f2011-03-23 11:00:15 -07002554 static int compareSignatures(Signature[] s1, Signature[] s2) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002555 if (s1 == null) {
2556 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 ? PackageManager.SIGNATURE_NEITHER_SIGNED
2558 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
2559 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002560 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
2562 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002563 HashSet<Signature> set1 = new HashSet<Signature>();
2564 for (Signature sig : s1) {
2565 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002567 HashSet<Signature> set2 = new HashSet<Signature>();
2568 for (Signature sig : s2) {
2569 set2.add(sig);
2570 }
2571 // Make sure s2 contains all signatures in s1.
2572 if (set1.equals(set2)) {
2573 return PackageManager.SIGNATURE_MATCH;
2574 }
2575 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 }
2577
2578 public String[] getPackagesForUid(int uid) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002579 uid = UserHandle.getAppId(uid);
Kenny Root447106f2011-03-23 11:00:15 -07002580 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002582 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002584 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 final int N = sus.packages.size();
Kenny Root447106f2011-03-23 11:00:15 -07002586 final String[] res = new String[N];
2587 final Iterator<PackageSetting> it = sus.packages.iterator();
2588 int i = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 while (it.hasNext()) {
2590 res[i++] = it.next().name;
2591 }
2592 return res;
2593 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002594 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 return new String[] { ps.name };
2596 }
2597 }
2598 return null;
2599 }
2600
2601 public String getNameForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07002602 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 synchronized (mPackages) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002604 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002606 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 return sus.name + ":" + sus.userId;
2608 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002609 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 return ps.name;
2611 }
2612 }
2613 return null;
2614 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 public int getUidForSharedUser(String sharedUserName) {
2617 if(sharedUserName == null) {
2618 return -1;
2619 }
Kenny Root447106f2011-03-23 11:00:15 -07002620 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002622 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
Amith Yamasani742a6712011-05-04 14:49:28 -07002623 if (suid == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 return -1;
2625 }
2626 return suid.userId;
2627 }
2628 }
2629
Ben Gruverdd72c9e2013-08-06 12:34:17 -07002630 public int getFlagsForUid(int uid) {
2631 synchronized (mPackages) {
2632 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
2633 if (obj instanceof SharedUserSetting) {
2634 final SharedUserSetting sus = (SharedUserSetting) obj;
2635 return sus.pkgFlags;
2636 } else if (obj instanceof PackageSetting) {
2637 final PackageSetting ps = (PackageSetting) obj;
2638 return ps.pkgFlags;
2639 }
2640 }
2641 return 0;
2642 }
2643
Amith Yamasani483f3b02012-03-13 16:08:00 -07002644 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002645 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002646 int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002647 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07002648 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
Amith Yamasani483f3b02012-03-13 16:08:00 -07002649 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2650 return chooseBestActivity(intent, resolvedType, flags, query, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02002651 }
2652
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002653 @Override
2654 public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
2655 IntentFilter filter, int match, ComponentName activity) {
2656 final int userId = UserHandle.getCallingUserId();
2657 if (DEBUG_PREFERRED) {
2658 Log.v(TAG, "setLastChosenActivity intent=" + intent
2659 + " resolvedType=" + resolvedType
2660 + " flags=" + flags
2661 + " filter=" + filter
2662 + " match=" + match
2663 + " activity=" + activity);
2664 filter.dump(new PrintStreamPrinter(System.out), " ");
2665 }
2666 intent.setComponent(null);
2667 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2668 // Find any earlier preferred or last chosen entries and nuke them
2669 findPreferredActivity(intent, resolvedType,
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002670 flags, query, 0, false, true, false, userId);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002671 // Add the new activity as the last chosen for this filter
2672 addPreferredActivityInternal(filter, match, null, activity, false, userId);
2673 }
2674
2675 @Override
2676 public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) {
2677 final int userId = UserHandle.getCallingUserId();
2678 if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
2679 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2680 return findPreferredActivity(intent, resolvedType, flags, query, 0,
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002681 false, false, false, userId);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002682 }
2683
Mihai Predaeae850c2009-05-13 10:13:48 +02002684 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002685 int flags, List<ResolveInfo> query, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686 if (query != null) {
2687 final int N = query.size();
2688 if (N == 1) {
2689 return query.get(0);
2690 } else if (N > 1) {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002691 final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 // If there is more than one activity with the same priority,
2693 // then let the user decide between them.
2694 ResolveInfo r0 = query.get(0);
2695 ResolveInfo r1 = query.get(1);
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002696 if (DEBUG_INTENT_MATCHING || debug) {
2697 Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002698 + r1.activityInfo.name + "=" + r1.priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 }
2700 // If the first activity has a higher priority, or a different
2701 // default, then it is always desireable to pick it.
2702 if (r0.priority != r1.priority
2703 || r0.preferredOrder != r1.preferredOrder
2704 || r0.isDefault != r1.isDefault) {
2705 return query.get(0);
2706 }
2707 // If we have saved a preference for a preferred activity for
2708 // this Intent, use that.
2709 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002710 flags, query, r0.priority, true, false, debug, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 if (ri != null) {
2712 return ri;
2713 }
Dianne Hackborn8da429e2012-09-23 12:52:19 -07002714 if (userId != 0) {
2715 ri = new ResolveInfo(mResolveInfo);
2716 ri.activityInfo = new ActivityInfo(ri.activityInfo);
2717 ri.activityInfo.applicationInfo = new ApplicationInfo(
2718 ri.activityInfo.applicationInfo);
2719 ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
2720 UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
2721 return ri;
2722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 return mResolveInfo;
2724 }
2725 }
2726 return null;
2727 }
2728
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002729 ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
2730 List<ResolveInfo> query, int priority, boolean always,
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002731 boolean removeMatches, boolean debug, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002732 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002733 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 synchronized (mPackages) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002735 if (intent.getSelector() != null) {
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002736 intent = intent.getSelector();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
Dianne Hackborn63092712012-10-07 14:45:35 -07002739 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002740 // Get the list of preferred activities that handle the intent
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002741 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
Dianne Hackborn63092712012-10-07 14:45:35 -07002742 List<PreferredActivity> prefs = pir != null
2743 ? pir.queryIntent(intent, resolvedType,
2744 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
2745 : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746 if (prefs != null && prefs.size() > 0) {
2747 // First figure out how good the original match set is.
2748 // We will only allow preferred activities that came
2749 // from the same match quality.
2750 int match = 0;
Kenny Root447106f2011-03-23 11:00:15 -07002751
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002752 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match...");
Kenny Root447106f2011-03-23 11:00:15 -07002753
2754 final int N = query.size();
2755 for (int j=0; j<N; j++) {
2756 final ResolveInfo ri = query.get(j);
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002757 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Match for " + ri.activityInfo
2758 + ": 0x" + Integer.toHexString(match));
Kenny Root447106f2011-03-23 11:00:15 -07002759 if (ri.match > match) {
2760 match = ri.match;
2761 }
2762 }
2763
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002764 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Best match: 0x"
2765 + Integer.toHexString(match));
Kenny Root447106f2011-03-23 11:00:15 -07002766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 match &= IntentFilter.MATCH_CATEGORY_MASK;
2768 final int M = prefs.size();
2769 for (int i=0; i<M; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002770 final PreferredActivity pa = prefs.get(i);
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002771 if (DEBUG_PREFERRED || debug) {
2772 Slog.v(TAG, "Checking PreferredActivity ds="
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002773 + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>")
2774 + "\n component=" + pa.mPref.mComponent);
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002775 pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002776 }
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002777 if (pa.mPref.mMatch != match) {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002778 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping bad match "
2779 + Integer.toHexString(pa.mPref.mMatch));
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002780 continue;
2781 }
2782 // If it's not an "always" type preferred activity and that's what we're
2783 // looking for, skip it.
2784 if (always && !pa.mPref.mAlways) {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002785 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 continue;
2787 }
Dianne Hackborn77119bc2012-10-23 14:32:48 -07002788 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent,
2789 flags | PackageManager.GET_DISABLED_COMPONENTS, userId);
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002790 if (DEBUG_PREFERRED || debug) {
2791 Slog.v(TAG, "Found preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002792 if (ai != null) {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002793 ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
Marco Nelissend85621c2010-09-03 09:25:33 -07002794 } else {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002795 Slog.v(TAG, " null");
Marco Nelissend85621c2010-09-03 09:25:33 -07002796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002797 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002798 if (ai == null) {
2799 // This previously registered preferred activity
2800 // component is no longer known. Most likely an update
2801 // to the app was installed and in the new version this
2802 // component no longer exists. Clean it up by removing
2803 // it from the preferred activities list, and skip it.
2804 Slog.w(TAG, "Removing dangling preferred activity: "
2805 + pa.mPref.mComponent);
Dianne Hackborn63092712012-10-07 14:45:35 -07002806 pir.removeFilter(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -08002807 continue;
2808 }
2809 for (int j=0; j<N; j++) {
2810 final ResolveInfo ri = query.get(j);
2811 if (!ri.activityInfo.applicationInfo.packageName
2812 .equals(ai.applicationInfo.packageName)) {
2813 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002815 if (!ri.activityInfo.name.equals(ai.name)) {
2816 continue;
2817 }
2818
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002819 if (removeMatches) {
2820 pir.removeFilter(pa);
2821 if (DEBUG_PREFERRED) {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002822 Slog.v(TAG, "Removing match " + pa.mPref.mComponent);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002823 }
2824 break;
2825 }
2826
2827 // Okay we found a previously set preferred or last chosen app.
Dianne Hackborn04505102012-02-29 12:34:04 -08002828 // If the result set is different from when this
2829 // was created, we need to clear it and re-ask the
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002830 // user their preference, if we're looking for an "always" type entry.
2831 if (always && !pa.mPref.sameSet(query, priority)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08002832 Slog.i(TAG, "Result set changed, dropping preferred activity for "
2833 + intent + " type " + resolvedType);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002834 if (DEBUG_PREFERRED) {
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002835 Slog.v(TAG, "Removing preferred activity since set changed "
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002836 + pa.mPref.mComponent);
2837 }
Dianne Hackborn63092712012-10-07 14:45:35 -07002838 pir.removeFilter(pa);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002839 // Re-add the filter as a "last chosen" entry (!always)
2840 PreferredActivity lastChosen = new PreferredActivity(
2841 pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
2842 pir.addFilter(lastChosen);
2843 mSettings.writePackageRestrictionsLPr(userId);
Dianne Hackborn04505102012-02-29 12:34:04 -08002844 return null;
2845 }
2846
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002847 // Yay! Either the set matched or we're looking for the last chosen
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002848 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: "
2849 + ri.activityInfo.packageName + "/" + ri.activityInfo.name);
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002850 mSettings.writePackageRestrictionsLPr(userId);
Dianne Hackborn04505102012-02-29 12:34:04 -08002851 return ri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 }
2853 }
2854 }
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -07002855 mSettings.writePackageRestrictionsLPr(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
Dianne Hackborn38ba6e92013-09-23 11:08:52 -07002857 if (DEBUG_PREFERRED || debug) Slog.v(TAG, "No preferred activity to return");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002858 return null;
2859 }
2860
Amith Yamasani483f3b02012-03-13 16:08:00 -07002861 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 public List<ResolveInfo> queryIntentActivities(Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002863 String resolvedType, int flags, int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002864 if (!sUserManager.exists(userId)) return Collections.emptyList();
Amith Yamasanif203aee2012-08-29 18:41:53 -07002865 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities");
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002866 ComponentName comp = intent.getComponent();
2867 if (comp == null) {
2868 if (intent.getSelector() != null) {
2869 intent = intent.getSelector();
2870 comp = intent.getComponent();
2871 }
2872 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002875 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002876 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 if (ai != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002878 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 ri.activityInfo = ai;
2880 list.add(ri);
2881 }
2882 return list;
2883 }
2884
Kenny Root447106f2011-03-23 11:00:15 -07002885 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002887 final String pkgName = intent.getPackage();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002888 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002889 return mActivities.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002890 }
Kenny Root447106f2011-03-23 11:00:15 -07002891 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002892 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002893 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002894 pkg.activities, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002895 }
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08002896 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
2898 }
2899
Amith Yamasani483f3b02012-03-13 16:08:00 -07002900 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2902 Intent[] specifics, String[] specificTypes, Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002903 String resolvedType, int flags, int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002904 if (!sUserManager.exists(userId)) return Collections.emptyList();
Amith Yamasanif203aee2012-08-29 18:41:53 -07002905 enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
2906 "query intent activity options");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 final String resultsAction = intent.getAction();
2908
Kenny Root447106f2011-03-23 11:00:15 -07002909 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
Amith Yamasani483f3b02012-03-13 16:08:00 -07002910 | PackageManager.GET_RESOLVED_FILTER, userId);
Kenny Root447106f2011-03-23 11:00:15 -07002911
2912 if (DEBUG_INTENT_MATCHING) {
2913 Log.v(TAG, "Query " + intent + ": " + results);
2914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915
2916 int specificsPos = 0;
2917 int N;
2918
2919 // todo: note that the algorithm used here is O(N^2). This
2920 // isn't a problem in our current environment, but if we start running
2921 // into situations where we have more than 5 or 10 matches then this
2922 // should probably be changed to something smarter...
2923
2924 // First we go through and resolve each of the specific items
2925 // that were supplied, taking care of removing any corresponding
2926 // duplicate items in the generic resolve list.
2927 if (specifics != null) {
2928 for (int i=0; i<specifics.length; i++) {
2929 final Intent sintent = specifics[i];
2930 if (sintent == null) {
2931 continue;
2932 }
2933
Kenny Root447106f2011-03-23 11:00:15 -07002934 if (DEBUG_INTENT_MATCHING) {
2935 Log.v(TAG, "Specific #" + i + ": " + sintent);
2936 }
2937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 String action = sintent.getAction();
2939 if (resultsAction != null && resultsAction.equals(action)) {
2940 // If this action was explicitly requested, then don't
2941 // remove things that have it.
2942 action = null;
2943 }
Kenny Root447106f2011-03-23 11:00:15 -07002944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 ResolveInfo ri = null;
2946 ActivityInfo ai = null;
Kenny Root447106f2011-03-23 11:00:15 -07002947
2948 ComponentName comp = sintent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 if (comp == null) {
2950 ri = resolveIntent(
2951 sintent,
2952 specificTypes != null ? specificTypes[i] : null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002953 flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 if (ri == null) {
2955 continue;
2956 }
2957 if (ri == mResolveInfo) {
2958 // ACK! Must do something better with this.
2959 }
2960 ai = ri.activityInfo;
2961 comp = new ComponentName(ai.applicationInfo.packageName,
2962 ai.name);
2963 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002964 ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 if (ai == null) {
2966 continue;
2967 }
2968 }
2969
2970 // Look for any generic query activities that are duplicates
2971 // of this specific one, and remove them from the results.
Kenny Root9718cf52011-02-23 16:45:26 -08002972 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 N = results.size();
2974 int j;
2975 for (j=specificsPos; j<N; j++) {
2976 ResolveInfo sri = results.get(j);
2977 if ((sri.activityInfo.name.equals(comp.getClassName())
2978 && sri.activityInfo.applicationInfo.packageName.equals(
2979 comp.getPackageName()))
2980 || (action != null && sri.filter.matchAction(action))) {
2981 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002982 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 TAG, "Removing duplicate item from " + j
2984 + " due to specific " + specificsPos);
2985 if (ri == null) {
2986 ri = sri;
2987 }
2988 j--;
2989 N--;
2990 }
2991 }
2992
2993 // Add this specific item to its proper place.
2994 if (ri == null) {
2995 ri = new ResolveInfo();
2996 ri.activityInfo = ai;
2997 }
2998 results.add(specificsPos, ri);
2999 ri.specificIndex = i;
3000 specificsPos++;
3001 }
3002 }
3003
3004 // Now we go through the remaining generic results and remove any
3005 // duplicate actions that are found here.
3006 N = results.size();
3007 for (int i=specificsPos; i<N-1; i++) {
3008 final ResolveInfo rii = results.get(i);
3009 if (rii.filter == null) {
3010 continue;
3011 }
3012
3013 // Iterate over all of the actions of this result's intent
3014 // filter... typically this should be just one.
3015 final Iterator<String> it = rii.filter.actionsIterator();
3016 if (it == null) {
3017 continue;
3018 }
3019 while (it.hasNext()) {
3020 final String action = it.next();
3021 if (resultsAction != null && resultsAction.equals(action)) {
3022 // If this action was explicitly requested, then don't
3023 // remove things that have it.
3024 continue;
3025 }
3026 for (int j=i+1; j<N; j++) {
3027 final ResolveInfo rij = results.get(j);
3028 if (rij.filter != null && rij.filter.hasAction(action)) {
3029 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08003030 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 TAG, "Removing duplicate item from " + j
3032 + " due to action " + action + " at " + i);
3033 j--;
3034 N--;
3035 }
3036 }
3037 }
3038
3039 // If the caller didn't request filter information, drop it now
3040 // so we don't have to marshall/unmarshall it.
3041 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
3042 rii.filter = null;
3043 }
3044 }
3045
3046 // Filter out the caller activity if so requested.
3047 if (caller != null) {
3048 N = results.size();
3049 for (int i=0; i<N; i++) {
3050 ActivityInfo ainfo = results.get(i).activityInfo;
3051 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
3052 && caller.getClassName().equals(ainfo.name)) {
3053 results.remove(i);
3054 break;
3055 }
3056 }
3057 }
3058
3059 // If the caller didn't request filter information,
3060 // drop them now so we don't have to
3061 // marshall/unmarshall it.
3062 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
3063 N = results.size();
3064 for (int i=0; i<N; i++) {
3065 results.get(i).filter = null;
3066 }
3067 }
3068
Kenny Root9718cf52011-02-23 16:45:26 -08003069 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 return results;
3071 }
3072
Amith Yamasani483f3b02012-03-13 16:08:00 -07003073 @Override
3074 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
3075 int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003076 if (!sUserManager.exists(userId)) return Collections.emptyList();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003077 ComponentName comp = intent.getComponent();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08003078 if (comp == null) {
3079 if (intent.getSelector() != null) {
3080 intent = intent.getSelector();
3081 comp = intent.getComponent();
3082 }
3083 }
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003084 if (comp != null) {
3085 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07003086 ActivityInfo ai = getReceiverInfo(comp, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003087 if (ai != null) {
3088 ResolveInfo ri = new ResolveInfo();
3089 ri.activityInfo = ai;
3090 list.add(ri);
3091 }
3092 return list;
3093 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003094
Kenny Root447106f2011-03-23 11:00:15 -07003095 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003097 String pkgName = intent.getPackage();
3098 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07003099 return mReceivers.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003100 }
Kenny Root447106f2011-03-23 11:00:15 -07003101 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003102 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07003103 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
3104 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003105 }
3106 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 }
3108 }
3109
Amith Yamasani483f3b02012-03-13 16:08:00 -07003110 @Override
3111 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
3112 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07003113 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 if (query != null) {
3115 if (query.size() >= 1) {
3116 // If there is more than one service with the same priority,
3117 // just arbitrarily pick the first one.
3118 return query.get(0);
3119 }
3120 }
3121 return null;
3122 }
3123
Amith Yamasani483f3b02012-03-13 16:08:00 -07003124 @Override
3125 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
3126 int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003127 if (!sUserManager.exists(userId)) return Collections.emptyList();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08003128 ComponentName comp = intent.getComponent();
3129 if (comp == null) {
3130 if (intent.getSelector() != null) {
3131 intent = intent.getSelector();
3132 comp = intent.getComponent();
3133 }
3134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003136 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07003137 final ServiceInfo si = getServiceInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 if (si != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003139 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 ri.serviceInfo = si;
3141 list.add(ri);
3142 }
3143 return list;
3144 }
3145
Kenny Root447106f2011-03-23 11:00:15 -07003146 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003148 String pkgName = intent.getPackage();
3149 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07003150 return mServices.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003151 }
Kenny Root447106f2011-03-23 11:00:15 -07003152 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003153 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07003154 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
3155 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07003156 }
3157 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 }
3159 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003160
Amith Yamasani151ec4c2012-09-07 19:25:16 -07003161 @Override
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003162 public List<ResolveInfo> queryIntentContentProviders(
3163 Intent intent, String resolvedType, int flags, int userId) {
3164 if (!sUserManager.exists(userId)) return Collections.emptyList();
3165 ComponentName comp = intent.getComponent();
3166 if (comp == null) {
3167 if (intent.getSelector() != null) {
3168 intent = intent.getSelector();
3169 comp = intent.getComponent();
3170 }
3171 }
3172 if (comp != null) {
3173 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
3174 final ProviderInfo pi = getProviderInfo(comp, flags, userId);
3175 if (pi != null) {
3176 final ResolveInfo ri = new ResolveInfo();
3177 ri.providerInfo = pi;
3178 list.add(ri);
3179 }
3180 return list;
3181 }
3182
3183 // reader
3184 synchronized (mPackages) {
3185 String pkgName = intent.getPackage();
3186 if (pkgName == null) {
3187 return mProviders.queryIntent(intent, resolvedType, flags, userId);
3188 }
3189 final PackageParser.Package pkg = mPackages.get(pkgName);
3190 if (pkg != null) {
3191 return mProviders.queryIntentForPackage(
3192 intent, resolvedType, flags, pkg.providers, userId);
3193 }
3194 return null;
3195 }
3196 }
3197
3198 @Override
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003199 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07003200 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani151ec4c2012-09-07 19:25:16 -07003201
3202 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203
Kenny Root447106f2011-03-23 11:00:15 -07003204 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 synchronized (mPackages) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003206 ArrayList<PackageInfo> list;
Kenny Root0e2c0f32011-04-15 17:50:10 -07003207 if (listUninstalled) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003208 list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
3209 for (PackageSetting ps : mSettings.mPackages.values()) {
3210 PackageInfo pi;
3211 if (ps.pkg != null) {
3212 pi = generatePackageInfo(ps.pkg, flags, userId);
3213 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07003214 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 }
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003216 if (pi != null) {
3217 list.add(pi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 }
3219 }
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003220 } else {
3221 list = new ArrayList<PackageInfo>(mPackages.size());
3222 for (PackageParser.Package p : mPackages.values()) {
3223 PackageInfo pi = generatePackageInfo(p, flags, userId);
3224 if (pi != null) {
3225 list.add(pi);
3226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003227 }
3228 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07003229
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003230 return new ParceledListSlice<PackageInfo>(list);
3231 }
3232 }
3233
3234 private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
3235 String[] permissions, boolean[] tmp, int flags, int userId) {
3236 int numMatch = 0;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003237 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003238 for (int i=0; i<permissions.length; i++) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003239 if (gp.grantedPermissions.contains(permissions[i])) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003240 tmp[i] = true;
3241 numMatch++;
3242 } else {
3243 tmp[i] = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 }
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003246 if (numMatch == 0) {
3247 return;
3248 }
3249 PackageInfo pi;
3250 if (ps.pkg != null) {
3251 pi = generatePackageInfo(ps.pkg, flags, userId);
3252 } else {
3253 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
3254 }
3255 if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
3256 if (numMatch == permissions.length) {
3257 pi.requestedPermissions = permissions;
3258 } else {
3259 pi.requestedPermissions = new String[numMatch];
3260 numMatch = 0;
3261 for (int i=0; i<permissions.length; i++) {
3262 if (tmp[i]) {
3263 pi.requestedPermissions[numMatch] = permissions[i];
3264 numMatch++;
3265 }
3266 }
3267 }
3268 }
3269 list.add(pi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
3271
Amith Yamasani483f3b02012-03-13 16:08:00 -07003272 @Override
Dianne Hackborne7991752013-01-16 17:56:46 -08003273 public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003274 String[] permissions, int flags, int userId) {
Dianne Hackborne7991752013-01-16 17:56:46 -08003275 if (!sUserManager.exists(userId)) return null;
Dianne Hackborne7991752013-01-16 17:56:46 -08003276 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
3277
3278 // writer
3279 synchronized (mPackages) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003280 ArrayList<PackageInfo> list = new ArrayList<PackageInfo>();
3281 boolean[] tmpBools = new boolean[permissions.length];
Dianne Hackborne7991752013-01-16 17:56:46 -08003282 if (listUninstalled) {
3283 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003284 addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId);
Dianne Hackborne7991752013-01-16 17:56:46 -08003285 }
3286 } else {
3287 for (PackageParser.Package pkg : mPackages.values()) {
3288 PackageSetting ps = (PackageSetting)pkg.mExtras;
3289 if (ps != null) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003290 addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
3291 userId);
3292 }
3293 }
3294 }
3295
3296 return new ParceledListSlice<PackageInfo>(list);
3297 }
3298 }
3299
3300 @Override
3301 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
3302 if (!sUserManager.exists(userId)) return null;
3303 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
3304
3305 // writer
3306 synchronized (mPackages) {
3307 ArrayList<ApplicationInfo> list;
3308 if (listUninstalled) {
3309 list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
3310 for (PackageSetting ps : mSettings.mPackages.values()) {
3311 ApplicationInfo ai;
3312 if (ps.pkg != null) {
3313 ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
3314 ps.readUserState(userId), userId);
3315 } else {
3316 ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
3317 }
3318 if (ai != null) {
3319 list.add(ai);
3320 }
3321 }
3322 } else {
3323 list = new ArrayList<ApplicationInfo>(mPackages.size());
3324 for (PackageParser.Package p : mPackages.values()) {
3325 if (p.mExtras != null) {
3326 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
3327 ((PackageSetting)p.mExtras).readUserState(userId), userId);
3328 if (ai != null) {
3329 list.add(ai);
Dianne Hackborne7991752013-01-16 17:56:46 -08003330 }
3331 }
3332 }
3333 }
3334
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003335 return new ParceledListSlice<ApplicationInfo>(list);
Dianne Hackborne7991752013-01-16 17:56:46 -08003336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 }
3338
3339 public List<ApplicationInfo> getPersistentApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07003340 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341
Kenny Root447106f2011-03-23 11:00:15 -07003342 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003344 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003345 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003347 final PackageParser.Package p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 if (p.applicationInfo != null
3349 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07003350 && (!mSafeMode || isSystemApp(p))) {
Amith Yamasani13593602012-03-22 16:16:17 -07003351 PackageSetting ps = mSettings.mPackages.get(p.packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003352 if (ps != null) {
3353 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
3354 ps.readUserState(userId), userId);
3355 if (ai != null) {
3356 finalList.add(ai);
3357 }
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360 }
3361 }
3362
3363 return finalList;
3364 }
3365
Amith Yamasani483f3b02012-03-13 16:08:00 -07003366 @Override
3367 public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07003368 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07003369 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 synchronized (mPackages) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003371 final PackageParser.Provider provider = mProvidersByAuthority.get(name);
Amith Yamasani13593602012-03-22 16:16:17 -07003372 PackageSetting ps = provider != null
3373 ? mSettings.mPackages.get(provider.owner.packageName)
3374 : null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003375 return ps != null
Amith Yamasani483f3b02012-03-13 16:08:00 -07003376 && mSettings.isEnabledLPr(provider.info, flags, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 && (!mSafeMode || (provider.info.applicationInfo.flags
3378 &ApplicationInfo.FLAG_SYSTEM) != 0)
Amith Yamasani13593602012-03-22 16:16:17 -07003379 ? PackageParser.generateProviderInfo(provider, flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003380 ps.readUserState(userId), userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381 : null;
3382 }
3383 }
3384
Fred Quintana718d8a22009-04-29 17:53:20 -07003385 /**
3386 * @deprecated
3387 */
Kenny Root60f7ad82011-03-22 12:49:06 -07003388 @Deprecated
3389 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07003390 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 synchronized (mPackages) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003392 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority
3393 .entrySet().iterator();
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003394 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 while (i.hasNext()) {
3396 Map.Entry<String, PackageParser.Provider> entry = i.next();
3397 PackageParser.Provider p = entry.getValue();
Amith Yamasani13593602012-03-22 16:16:17 -07003398 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003400 if (ps != null && p.syncable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 && (!mSafeMode || (p.info.applicationInfo.flags
3402 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003403 ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
3404 ps.readUserState(userId), userId);
3405 if (info != null) {
3406 outNames.add(entry.getKey());
3407 outInfo.add(info);
3408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 }
3410 }
3411 }
3412 }
3413
3414 public List<ProviderInfo> queryContentProviders(String processName,
3415 int uid, int flags) {
3416 ArrayList<ProviderInfo> finalList = null;
Kenny Root447106f2011-03-23 11:00:15 -07003417 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 synchronized (mPackages) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003419 final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
Amith Yamasani483f3b02012-03-13 16:08:00 -07003420 final int userId = processName != null ?
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003421 UserHandle.getUserId(uid) : UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003423 final PackageParser.Provider p = i.next();
Amith Yamasani13593602012-03-22 16:16:17 -07003424 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003425 if (ps != null && p.info.authority != null
Kenny Root447106f2011-03-23 11:00:15 -07003426 && (processName == null
3427 || (p.info.processName.equals(processName)
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003428 && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
Amith Yamasani483f3b02012-03-13 16:08:00 -07003429 && mSettings.isEnabledLPr(p.info, flags, userId)
Kenny Root447106f2011-03-23 11:00:15 -07003430 && (!mSafeMode
3431 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 if (finalList == null) {
3433 finalList = new ArrayList<ProviderInfo>(3);
3434 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003435 ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
3436 ps.readUserState(userId), userId);
Dianne Hackborn4428e172012-08-24 17:43:05 -07003437 if (info != null) {
3438 finalList.add(info);
3439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 }
3441 }
3442 }
3443
3444 if (finalList != null) {
3445 Collections.sort(finalList, mProviderInitOrderSorter);
3446 }
3447
3448 return finalList;
3449 }
3450
3451 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
3452 int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07003453 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 synchronized (mPackages) {
3455 final PackageParser.Instrumentation i = mInstrumentation.get(name);
3456 return PackageParser.generateInstrumentationInfo(i, flags);
3457 }
3458 }
3459
3460 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
3461 int flags) {
3462 ArrayList<InstrumentationInfo> finalList =
3463 new ArrayList<InstrumentationInfo>();
3464
Kenny Root447106f2011-03-23 11:00:15 -07003465 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003467 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003469 final PackageParser.Instrumentation p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 if (targetPackage == null
3471 || targetPackage.equals(p.info.targetPackage)) {
Dianne Hackborn4428e172012-08-24 17:43:05 -07003472 InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p,
3473 flags);
3474 if (ii != null) {
3475 finalList.add(ii);
3476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 }
3478 }
3479 }
3480
3481 return finalList;
3482 }
3483
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003484 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07003486 if (files == null) {
3487 Log.d(TAG, "No files in app dir " + dir);
3488 return;
3489 }
3490
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003491 if (DEBUG_PACKAGE_SCANNING) {
Christopher Tateccbf84f2013-05-08 15:25:41 -07003492 Log.d(TAG, "Scanning app dir " + dir + " scanMode=" + scanMode
3493 + " flags=0x" + Integer.toHexString(flags));
Joe Onorato431bb222010-10-18 19:13:23 -04003494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495
3496 int i;
3497 for (i=0; i<files.length; i++) {
3498 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003499 if (!isPackageFilename(files[i])) {
3500 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003501 continue;
3502 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003503 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003504 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003505 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003506 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
3507 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003508 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003509 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003510 file.delete();
3511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 }
3513 }
3514
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003515 private static File getSettingsProblemFile() {
3516 File dataDir = Environment.getDataDirectory();
3517 File systemDir = new File(dataDir, "system");
3518 File fname = new File(systemDir, "uiderrors.txt");
3519 return fname;
3520 }
3521
Kenny Rootcf0b38c2011-03-22 14:17:59 -07003522 static void reportSettingsProblem(int priority, String msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003524 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 FileOutputStream out = new FileOutputStream(fname, true);
Dianne Hackborn8c841092013-06-24 13:46:13 -07003526 PrintWriter pw = new FastPrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003527 SimpleDateFormat formatter = new SimpleDateFormat();
3528 String dateString = formatter.format(new Date(System.currentTimeMillis()));
3529 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 pw.close();
3531 FileUtils.setPermissions(
3532 fname.toString(),
3533 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
3534 -1, -1);
3535 } catch (java.io.IOException e) {
3536 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003537 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 }
3539
3540 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
3541 PackageParser.Package pkg, File srcFile, int parseFlags) {
3542 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07003543 if (ps != null
3544 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07003545 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07003546 if (ps.signatures.mSignatures != null
3547 && ps.signatures.mSignatures.length != 0) {
3548 // Optimization: reuse the existing cached certificates
3549 // if the package appears to be unchanged.
3550 pkg.mSignatures = ps.signatures.mSignatures;
3551 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 }
Jeff Browne7600722010-04-07 18:28:23 -07003553
3554 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003555 } else {
Jeff Browne7600722010-04-07 18:28:23 -07003556 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
3557 }
3558
3559 if (!pp.collectCertificates(pkg, parseFlags)) {
3560 mLastScanError = pp.getParseError();
3561 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 }
3563 }
3564 return true;
3565 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 /*
3568 * Scan a package and return the newly parsed package.
3569 * Returns null in case of errors and the error code is stored in mLastScanError
3570 */
3571 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003572 int parseFlags, int scanMode, long currentTime, UserHandle user) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003574 String scanPath = scanFile.getPath();
Dianne Hackbornc895be72013-03-11 17:48:43 -07003575 if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003577 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07003579 pp.setOnlyCoreApps(mOnlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003581 scanPath, mMetrics, parseFlags);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 if (pkg == null) {
3584 mLastScanError = pp.getParseError();
3585 return null;
3586 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003587
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003588 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 PackageSetting updatedPkg;
Kenny Root447106f2011-03-23 11:00:15 -07003590 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003592 // Look to see if we already know about this package.
3593 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003594 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003595 // This package has been renamed to its original name. Let's
3596 // use that.
Kenny Root447106f2011-03-23 11:00:15 -07003597 ps = mSettings.peekPackageLPr(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003598 }
3599 // If there was no original package, see one for the real package name.
3600 if (ps == null) {
Kenny Root447106f2011-03-23 11:00:15 -07003601 ps = mSettings.peekPackageLPr(pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003602 }
3603 // Check to see if this package could be hiding/updating a system
3604 // package. Must look for it either under the original or real
3605 // package name depending on our state.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003606 updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003607 if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003609 // First check if this is a system package that may involve an update
3610 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07003611 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003612 // The path has changed from what was last scanned... check the
3613 // version of the new path against what we have stored to determine
3614 // what to do.
Dianne Hackbornc895be72013-03-11 17:48:43 -07003615 if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003616 if (pkg.mVersionCode < ps.versionCode) {
3617 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003618 // Ignore entry. Skip it.
3619 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003620 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003621 + " better than this " + pkg.mVersionCode);
Dianne Hackbornc4d27a72013-01-22 18:30:17 -08003622 if (!updatedPkg.codePath.equals(scanFile)) {
3623 Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
3624 + ps.name + " changing from " + updatedPkg.codePathString
3625 + " to " + scanFile);
3626 updatedPkg.codePath = scanFile;
Christopher Tate9f088202013-10-22 15:36:01 -07003627 updatedPkg.codePathString = scanFile.toString();
3628 // This is the point at which we know that the system-disk APK
3629 // for this package has moved during a reboot (e.g. due to an OTA),
3630 // so we need to reevaluate it for privilege policy.
3631 if (locationIsPrivileged(scanFile)) {
3632 updatedPkg.pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
3633 }
Dianne Hackbornc4d27a72013-01-22 18:30:17 -08003634 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07003635 updatedPkg.pkg = pkg;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003636 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3637 return null;
3638 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003639 // The current app on the system partion is better than
3640 // what we have updated to on the data partition; switch
3641 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003642 // At this point, its safely assumed that package installation for
3643 // apps in system partition will go through. If not there won't be a working
3644 // version of the app
Kenny Root447106f2011-03-23 11:00:15 -07003645 // writer
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003646 synchronized (mPackages) {
3647 // Just remove the loaded entries from package lists.
3648 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003649 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003650 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003651 + "reverting from " + ps.codePathString
3652 + ": new version " + pkg.mVersionCode
3653 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003654
3655 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3656 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Dianne Hackborn4428e172012-08-24 17:43:05 -07003657 synchronized (mInstallLock) {
Kenny Root208d3412012-05-07 19:42:35 -07003658 args.cleanUpResourcesLI();
3659 }
3660 synchronized (mPackages) {
3661 mSettings.enableSystemPackageLPw(ps.name);
3662 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 }
3665 }
Kenny Root208d3412012-05-07 19:42:35 -07003666
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003667 if (updatedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07003668 // An updated system app will not have the PARSE_IS_SYSTEM flag set
3669 // initially
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003670 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
Naofumi Harada719b3b82014-01-21 10:29:36 +09003671
3672 // An updated privileged app will not have the PARSE_IS_PRIVILEGED
3673 // flag set initially
3674 if ((updatedPkg.pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
3675 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
3676 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003677 }
3678 // Verify certificates against what was last scanned
3679 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003680 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003681 return null;
3682 }
Kenny Root208d3412012-05-07 19:42:35 -07003683
3684 /*
3685 * A new system app appeared, but we already had a non-system one of the
3686 * same name installed earlier.
3687 */
3688 boolean shouldHideSystemApp = false;
3689 if (updatedPkg == null && ps != null
3690 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
3691 /*
3692 * Check to make sure the signatures match first. If they don't,
3693 * wipe the installed application and its data.
3694 */
3695 if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
3696 != PackageManager.SIGNATURE_MATCH) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003697 if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!");
Christopher Tateacee6e92013-05-14 16:11:44 -07003698 deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
Kenny Root208d3412012-05-07 19:42:35 -07003699 ps = null;
3700 } else {
3701 /*
3702 * If the newly-added system app is an older version than the
3703 * already installed version, hide it. It will be scanned later
3704 * and re-added like an update.
3705 */
3706 if (pkg.mVersionCode < ps.versionCode) {
3707 shouldHideSystemApp = true;
3708 } else {
3709 /*
3710 * The newly found system app is a newer version that the
3711 * one previously installed. Simply remove the
3712 * already-installed application and replace it with our own
3713 * while keeping the application data.
3714 */
3715 Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
3716 + ps.codePathString + ": new version " + pkg.mVersionCode
3717 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003718 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3719 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Dianne Hackborn4428e172012-08-24 17:43:05 -07003720 synchronized (mInstallLock) {
Kenny Root208d3412012-05-07 19:42:35 -07003721 args.cleanUpResourcesLI();
3722 }
3723 }
3724 }
3725 }
3726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 // The apk is forward locked (not public) if its code and resources
Masanori Ogino2d910072012-05-07 16:44:48 +09003728 // are kept in different files. (except for app in either system or
3729 // vendor path).
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003730 // TODO grab this value from PackageSettings
Masanori Ogino2d910072012-05-07 16:44:48 +09003731 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
3732 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
3733 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
3734 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07003735 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003736
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003737 String codePath = null;
3738 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003739 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
3740 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003741 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003742 } else {
3743 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003744 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003745 }
3746 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003747 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003748 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003749
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003750 codePath = pkg.mScanPath;
3751 // Set application objects path explicitly.
3752 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 // Note that we invoke the following method only if we are about to unpack an application
Kenny Root208d3412012-05-07 19:42:35 -07003754 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003755 | SCAN_UPDATE_SIGNATURE, currentTime, user);
Kenny Root208d3412012-05-07 19:42:35 -07003756
3757 /*
3758 * If the system app should be overridden by a previously installed
3759 * data, hide the system app now and let the /data/app scan pick it up
3760 * again.
3761 */
3762 if (shouldHideSystemApp) {
3763 synchronized (mPackages) {
3764 /*
3765 * We have to grant systems permissions before we hide, because
3766 * grantPermissions will assume the package update is trying to
3767 * expand its permissions.
3768 */
3769 grantPermissionsLPw(pkg, true);
3770 mSettings.disableSystemPackageLPw(pkg.packageName);
3771 }
3772 }
3773
3774 return scannedPkg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 }
3776
Kenny Root85387d72010-08-26 10:13:11 -07003777 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
3778 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003779 pkg.mPath = pkg.mScanPath = destCodePath;
3780 pkg.applicationInfo.sourceDir = destCodePath;
3781 pkg.applicationInfo.publicSourceDir = destResPath;
3782 }
3783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 private static String fixProcessName(String defProcessName,
3785 String processName, int uid) {
3786 if (processName == null) {
3787 return defProcessName;
3788 }
3789 return processName;
3790 }
3791
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003792 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003793 PackageParser.Package pkg) {
3794 if (pkgSetting.signatures.mSignatures != null) {
3795 // Already existing package. Make sure signatures match
Kenny Root447106f2011-03-23 11:00:15 -07003796 if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003797 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003798 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003799 + " signatures do not match the previously installed version; ignoring!");
3800 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 return false;
3802 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003803 }
3804 // Check for shared user signatures
3805 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003806 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003807 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3808 Slog.e(TAG, "Package " + pkg.packageName
3809 + " has no signatures that match those in shared user "
3810 + pkgSetting.sharedUser.name + "; ignoring!");
3811 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
3812 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 }
3815 return true;
3816 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003817
Kenny Root461ff1f2011-08-09 09:43:03 -07003818 /**
3819 * Enforces that only the system UID or root's UID can call a method exposed
3820 * via Binder.
3821 *
3822 * @param message used as message if SecurityException is thrown
3823 * @throws SecurityException if the caller is not system or root
3824 */
3825 private static final void enforceSystemOrRoot(String message) {
3826 final int uid = Binder.getCallingUid();
3827 if (uid != Process.SYSTEM_UID && uid != 0) {
3828 throw new SecurityException(message);
3829 }
3830 }
3831
Dianne Hackborn661cd522011-08-22 00:26:20 -07003832 public void performBootDexOpt() {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003833 HashSet<PackageParser.Package> pkgs = null;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003834 synchronized (mPackages) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003835 pkgs = mDeferredDexOpt;
3836 mDeferredDexOpt = null;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003837 }
3838 if (pkgs != null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003839 int i = 0;
3840 for (PackageParser.Package pkg : pkgs) {
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003841 if (!isFirstBoot()) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003842 i++;
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003843 try {
3844 ActivityManagerNative.getDefault().showBootMessage(
3845 mContext.getResources().getString(
3846 com.android.internal.R.string.android_upgrading_apk,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003847 i, pkgs.size()), true);
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003848 } catch (RemoteException e) {
3849 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003850 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07003851 PackageParser.Package p = pkg;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003852 synchronized (mInstallLock) {
3853 if (!p.mDidDexOpt) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003854 performDexOptLI(p, false, false, true);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003855 }
3856 }
3857 }
3858 }
3859 }
3860
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003861 public boolean performDexOpt(String packageName) {
Kenny Root461ff1f2011-08-09 09:43:03 -07003862 enforceSystemOrRoot("Only the system can request dexopt be performed");
3863
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003864 if (!mNoDexOpt) {
3865 return false;
3866 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003867
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003868 PackageParser.Package p;
3869 synchronized (mPackages) {
3870 p = mPackages.get(packageName);
3871 if (p == null || p.mDidDexOpt) {
3872 return false;
3873 }
3874 }
3875 synchronized (mInstallLock) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003876 return performDexOptLI(p, false, false, true) == DEX_OPT_PERFORMED;
3877 }
3878 }
3879
3880 private void performDexOptLibsLI(ArrayList<String> libs, boolean forceDex, boolean defer,
3881 HashSet<String> done) {
3882 for (int i=0; i<libs.size(); i++) {
3883 PackageParser.Package libPkg;
3884 String libName;
3885 synchronized (mPackages) {
3886 libName = libs.get(i);
3887 SharedLibraryEntry lib = mSharedLibraries.get(libName);
3888 if (lib != null && lib.apk != null) {
3889 libPkg = mPackages.get(lib.apk);
3890 } else {
3891 libPkg = null;
3892 }
3893 }
3894 if (libPkg != null && !done.contains(libName)) {
3895 performDexOptLI(libPkg, forceDex, defer, done);
3896 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003897 }
3898 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003899
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003900 static final int DEX_OPT_SKIPPED = 0;
3901 static final int DEX_OPT_PERFORMED = 1;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003902 static final int DEX_OPT_DEFERRED = 2;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003903 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003904
Dianne Hackbornc895be72013-03-11 17:48:43 -07003905 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
3906 HashSet<String> done) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003907 boolean performed = false;
Dianne Hackbornc895be72013-03-11 17:48:43 -07003908 if (done != null) {
3909 done.add(pkg.packageName);
3910 if (pkg.usesLibraries != null) {
3911 performDexOptLibsLI(pkg.usesLibraries, forceDex, defer, done);
3912 }
3913 if (pkg.usesOptionalLibraries != null) {
3914 performDexOptLibsLI(pkg.usesOptionalLibraries, forceDex, defer, done);
3915 }
3916 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003917 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003918 String path = pkg.mScanPath;
3919 int ret = 0;
3920 try {
3921 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003922 if (!forceDex && defer) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07003923 if (mDeferredDexOpt == null) {
3924 mDeferredDexOpt = new HashSet<PackageParser.Package>();
3925 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003926 mDeferredDexOpt.add(pkg);
3927 return DEX_OPT_DEFERRED;
3928 } else {
3929 Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
Kenny Root6a9b2cb2012-09-17 14:02:39 -07003930 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
3931 ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));
Dianne Hackborn661cd522011-08-22 00:26:20 -07003932 pkg.mDidDexOpt = true;
3933 performed = true;
3934 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003935 }
3936 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003937 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003938 ret = -1;
3939 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07003940 Slog.w(TAG, "IOException reading apk: " + path, e);
3941 ret = -1;
3942 } catch (dalvik.system.StaleDexCacheError e) {
3943 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
3944 ret = -1;
3945 } catch (Exception e) {
3946 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003947 ret = -1;
3948 }
3949 if (ret < 0) {
3950 //error from installer
3951 return DEX_OPT_FAILED;
3952 }
3953 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003954
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003955 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
3956 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08003957
Dianne Hackbornc895be72013-03-11 17:48:43 -07003958 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
3959 boolean inclDependencies) {
3960 HashSet<String> done;
3961 boolean performed = false;
3962 if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
3963 done = new HashSet<String>();
3964 done.add(pkg.packageName);
3965 } else {
3966 done = null;
3967 }
3968 return performDexOptLI(pkg, forceDex, defer, done);
3969 }
3970
Kenny Root447106f2011-03-23 11:00:15 -07003971 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003972 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003973 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003974 + " to " + newPkg.packageName
3975 + ": old package not in system partition");
3976 return false;
3977 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003978 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003979 + " to " + newPkg.packageName
3980 + ": old package still exists");
3981 return false;
3982 }
3983 return true;
3984 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003985
Amith Yamasani0b285492011-04-14 17:35:23 -07003986 File getDataPathForUser(int userId) {
3987 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003988 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003989
3990 private File getDataPathForPackage(String packageName, int userId) {
Kenny Root9c8625e2011-07-25 09:42:22 -07003991 /*
3992 * Until we fully support multiple users, return the directory we
3993 * previously would have. The PackageManagerTests will need to be
3994 * revised when this is changed back..
3995 */
3996 if (userId == 0) {
3997 return new File(mAppDataDir, packageName);
3998 } else {
3999 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07004000 + File.separator + packageName);
Kenny Root9c8625e2011-07-25 09:42:22 -07004001 }
Amith Yamasani0b285492011-04-14 17:35:23 -07004002 }
4003
Robert Craig0f40dc92013-03-25 06:33:03 -04004004 private int createDataDirsLI(String packageName, int uid, String seinfo) {
Dave Burke383fa182012-10-23 23:12:19 -07004005 int[] users = sUserManager.getUserIds();
Robert Craig0f40dc92013-03-25 06:33:03 -04004006 int res = mInstaller.install(packageName, uid, uid, seinfo);
Dave Burke383fa182012-10-23 23:12:19 -07004007 if (res < 0) {
4008 return res;
4009 }
4010 for (int user : users) {
4011 if (user != 0) {
4012 res = mInstaller.createUserData(packageName,
Robert Craig8643dc62013-07-29 09:06:51 -04004013 UserHandle.getUid(user, uid), user, seinfo);
Dave Burke383fa182012-10-23 23:12:19 -07004014 if (res < 0) {
4015 return res;
4016 }
Dianne Hackborn4428e172012-08-24 17:43:05 -07004017 }
4018 }
Dave Burke383fa182012-10-23 23:12:19 -07004019 return res;
Dianne Hackborn4428e172012-08-24 17:43:05 -07004020 }
4021
4022 private int removeDataDirsLI(String packageName) {
4023 int[] users = sUserManager.getUserIds();
4024 int res = 0;
4025 for (int user : users) {
4026 int resInner = mInstaller.remove(packageName, user);
4027 if (resInner < 0) {
4028 res = resInner;
4029 }
4030 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07004031
4032 final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
4033 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
4034 if (!nativeLibraryFile.delete()) {
4035 Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
4036 }
4037
Dianne Hackborn4428e172012-08-24 17:43:05 -07004038 return res;
4039 }
4040
Dianne Hackbornc895be72013-03-11 17:48:43 -07004041 private int addSharedLibraryLPw(final SharedLibraryEntry file, int num,
4042 PackageParser.Package changingLib) {
4043 if (file.path != null) {
4044 mTmpSharedLibraries[num] = file.path;
4045 return num+1;
4046 }
4047 PackageParser.Package p = mPackages.get(file.apk);
4048 if (changingLib != null && changingLib.packageName.equals(file.apk)) {
4049 // If we are doing this while in the middle of updating a library apk,
4050 // then we need to make sure to use that new apk for determining the
4051 // dependencies here. (We haven't yet finished committing the new apk
4052 // to the package manager state.)
4053 if (p == null || p.packageName.equals(changingLib.packageName)) {
4054 p = changingLib;
4055 }
4056 }
4057 if (p != null) {
4058 String path = p.mPath;
4059 for (int i=0; i<num; i++) {
4060 if (mTmpSharedLibraries[i].equals(path)) {
4061 return num;
4062 }
4063 }
4064 mTmpSharedLibraries[num] = p.mPath;
4065 return num+1;
4066 }
4067 return num;
4068 }
4069
4070 private boolean updateSharedLibrariesLPw(PackageParser.Package pkg,
4071 PackageParser.Package changingLib) {
4072 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
4073 if (mTmpSharedLibraries == null ||
4074 mTmpSharedLibraries.length < mSharedLibraries.size()) {
4075 mTmpSharedLibraries = new String[mSharedLibraries.size()];
4076 }
4077 int num = 0;
4078 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
4079 for (int i=0; i<N; i++) {
4080 final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesLibraries.get(i));
4081 if (file == null) {
4082 Slog.e(TAG, "Package " + pkg.packageName
4083 + " requires unavailable shared library "
4084 + pkg.usesLibraries.get(i) + "; failing!");
4085 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
4086 return false;
4087 }
4088 num = addSharedLibraryLPw(file, num, changingLib);
4089 }
4090 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
4091 for (int i=0; i<N; i++) {
4092 final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
4093 if (file == null) {
4094 Slog.w(TAG, "Package " + pkg.packageName
4095 + " desires unavailable shared library "
4096 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
4097 } else {
4098 num = addSharedLibraryLPw(file, num, changingLib);
4099 }
4100 }
4101 if (num > 0) {
4102 pkg.usesLibraryFiles = new String[num];
4103 System.arraycopy(mTmpSharedLibraries, 0,
4104 pkg.usesLibraryFiles, 0, num);
4105 } else {
4106 pkg.usesLibraryFiles = null;
4107 }
4108 }
4109 return true;
4110 }
4111
4112 private static boolean hasString(List<String> list, List<String> which) {
4113 if (list == null) {
4114 return false;
4115 }
4116 for (int i=list.size()-1; i>=0; i--) {
4117 for (int j=which.size()-1; j>=0; j--) {
4118 if (which.get(j).equals(list.get(i))) {
4119 return true;
4120 }
4121 }
4122 }
4123 return false;
4124 }
4125
4126 private void updateAllSharedLibrariesLPw() {
4127 for (PackageParser.Package pkg : mPackages.values()) {
4128 updateSharedLibrariesLPw(pkg, null);
4129 }
4130 }
4131
4132 private ArrayList<PackageParser.Package> updateAllSharedLibrariesLPw(
4133 PackageParser.Package changingPkg) {
4134 ArrayList<PackageParser.Package> res = null;
4135 for (PackageParser.Package pkg : mPackages.values()) {
4136 if (hasString(pkg.usesLibraries, changingPkg.libraryNames)
4137 || hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames)) {
4138 if (res == null) {
4139 res = new ArrayList<PackageParser.Package>();
4140 }
4141 res.add(pkg);
4142 updateSharedLibrariesLPw(pkg, changingPkg);
4143 }
4144 }
4145 return res;
4146 }
4147
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004148 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004149 int parseFlags, int scanMode, long currentTime, UserHandle user) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004150 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08004151 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
4152 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08004153 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004154 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08004155 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
4156 return null;
4157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
4160 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
4161 }
4162
Christopher Tateccbf84f2013-05-08 15:25:41 -07004163 if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
4164 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED;
4165 }
4166
Jose Limabb9682e2013-08-16 16:14:32 -07004167 if (mCustomResolverComponentName != null &&
4168 mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
4169 setUpCustomResolverActivity(pkg);
4170 }
4171
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004172 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 synchronized (mPackages) {
4174 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004175 Slog.w(TAG, "*************************************************");
4176 Slog.w(TAG, "Core android package being redefined. Skipping.");
Narayan Kamath65048bd2013-12-16 18:18:12 +00004177 Slog.w(TAG, " file=" + scanFile);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004178 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
4180 return null;
4181 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004182
Jose Limabb9682e2013-08-16 16:14:32 -07004183 // Set up information for our fall-back user intent resolution activity.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 mPlatformPackage = pkg;
4185 pkg.mVersionCode = mSdkVersion;
4186 mAndroidApplication = pkg.applicationInfo;
Jose Limabb9682e2013-08-16 16:14:32 -07004187
4188 if (!mResolverReplaced) {
4189 mResolveActivity.applicationInfo = mAndroidApplication;
4190 mResolveActivity.name = ResolverActivity.class.getName();
4191 mResolveActivity.packageName = mAndroidApplication.packageName;
4192 mResolveActivity.processName = "system:ui";
4193 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4194 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4195 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
4196 mResolveActivity.exported = true;
4197 mResolveActivity.enabled = true;
4198 mResolveInfo.activityInfo = mResolveActivity;
4199 mResolveInfo.priority = 0;
4200 mResolveInfo.preferredOrder = 0;
4201 mResolveInfo.match = 0;
4202 mResolveComponentName = new ComponentName(
4203 mAndroidApplication.packageName, mResolveActivity.name);
4204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
4206 }
4207
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004208 if (DEBUG_PACKAGE_SCANNING) {
4209 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4210 Log.d(TAG, "Scanning package " + pkg.packageName);
4211 }
4212
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004213 if (mPackages.containsKey(pkg.packageName)
4214 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004215 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
4218 return null;
4219 }
4220
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004221 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004222 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
4223 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 SharedUserSetting suid = null;
4226 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004227
Kenny Root502e9a42011-01-10 13:48:15 -08004228 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004229 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08004230 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004231 pkg.mRealPackage = null;
4232 pkg.mAdoptPermissions = null;
4233 }
Kenny Root502e9a42011-01-10 13:48:15 -08004234
Kenny Root447106f2011-03-23 11:00:15 -07004235 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 synchronized (mPackages) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07004237 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
4238 // Check all shared libraries and map to their actual file path.
4239 // We only do this here for apps not on a system dir, because those
4240 // are the only ones that can fail an install due to this. We
4241 // will take care of the system apps by updating all of their
4242 // library paths after the scan is done.
4243 if (!updateSharedLibrariesLPw(pkg, null)) {
4244 return null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004245 }
Kenny Root1683afa2011-01-07 14:27:50 -08004246 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 if (pkg.mSharedUserId != null) {
Ben Gruverdd72c9e2013-08-06 12:34:17 -07004249 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004251 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 + " for shared user failed");
4253 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4254 return null;
4255 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004256 if (DEBUG_PACKAGE_SCANNING) {
4257 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4258 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
4259 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004260 }
4261 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004262
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004263 // Check if we are renaming from an original package name.
4264 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004265 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08004266 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004267 // This package may need to be renamed to a previously
4268 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07004269 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08004270 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004271 // This package had originally been installed as the
4272 // original name, and we have already taken care of
4273 // transitioning to the new one. Just update the new
4274 // one to continue using the old name.
4275 realName = pkg.mRealPackage;
4276 if (!pkg.packageName.equals(renamed)) {
4277 // Callers into this function may have already taken
4278 // care of renaming the package; only do it here if
4279 // it is not already done.
4280 pkg.setPackageName(renamed);
4281 }
4282
Dianne Hackbornc1552392010-03-03 16:19:01 -08004283 } else {
4284 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07004285 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08004286 pkg.mOriginalPackages.get(i))) != null) {
4287 // We do have the package already installed under its
4288 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07004289 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08004290 // New package is not compatible with original.
4291 origPackage = null;
4292 continue;
4293 } else if (origPackage.sharedUser != null) {
4294 // Make sure uid is compatible between packages.
4295 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004296 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08004297 + " to " + pkg.packageName + ": old uid "
4298 + origPackage.sharedUser.name
4299 + " differs from " + pkg.mSharedUserId);
4300 origPackage = null;
4301 continue;
4302 }
4303 } else {
4304 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
4305 + pkg.packageName + " to old name " + origPackage.name);
4306 }
4307 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004308 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004309 }
4310 }
4311 }
4312
4313 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004314 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004315 + " was transferred to another, but its .apk remains");
4316 }
4317
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004318 // Just create the setting, don't add it yet. For already existing packages
4319 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07004320 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07004321 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004322 pkg.applicationInfo.flags, user, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004323 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004324 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4326 return null;
4327 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004328
4329 if (pkgSetting.origPackage != null) {
4330 // If we are first transitioning from an original package,
4331 // fix up the new package's name now. We need to do this after
4332 // looking up the package under its new name, so getPackageLP
4333 // can take care of fiddling things correctly.
4334 pkg.setPackageName(origPackage.name);
4335
4336 // File a report about this.
4337 String msg = "New package " + pkgSetting.realName
4338 + " renamed to replace old package " + pkgSetting.name;
4339 reportSettingsProblem(Log.WARN, msg);
4340
4341 // Make a note of it.
4342 mTransferedPackages.add(origPackage.name);
4343
4344 // No longer need to retain this.
4345 pkgSetting.origPackage = null;
4346 }
4347
4348 if (realName != null) {
4349 // Make a note of it.
4350 mTransferedPackages.add(pkg.packageName);
4351 }
4352
Kenny Rootc52d6fd2012-05-07 23:04:52 -07004353 if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
4355 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004356
Robert Craig0f40dc92013-03-25 06:33:03 -04004357 if (mFoundPolicyFile) {
4358 SELinuxMMAC.assignSeinfoValue(pkg);
4359 }
4360
Amith Yamasani13593602012-03-22 16:16:17 -07004361 pkg.applicationInfo.uid = pkgSetting.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004363
Suchi Amalapurapuae181712010-03-30 14:01:02 -07004364 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004365 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 return null;
4367 }
4368 // The signature has changed, but this package is in the system
4369 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07004370 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 // However... if this package is part of a shared user, but it
4372 // doesn't match the signature of the shared user, let's fail.
4373 // What this means is that you can't change the signatures
4374 // associated with an overall shared user, which doesn't seem all
4375 // that unreasonable.
4376 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004377 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07004378 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
4379 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4381 return null;
4382 }
4383 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004384 // File a report about this.
4385 String msg = "System package " + pkg.packageName
4386 + " signature changed; retaining data.";
4387 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004389
The Android Open Source Project10592532009-03-18 17:39:46 -07004390 // Verify that this new package doesn't have any content providers
4391 // that conflict with existing packages. Only do this if the
4392 // package isn't already installed, since we don't want to break
4393 // things that are installed.
4394 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08004395 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07004396 int i;
4397 for (i=0; i<N; i++) {
4398 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004399 if (p.info.authority != null) {
4400 String names[] = p.info.authority.split(";");
4401 for (int j = 0; j < names.length; j++) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004402 if (mProvidersByAuthority.containsKey(names[j])) {
4403 PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004404 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004405 " (in package " + pkg.applicationInfo.packageName +
4406 ") is already used by "
4407 + ((other != null && other.getComponentName() != null)
4408 ? other.getComponentName().getPackageName() : "?"));
4409 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
4410 return null;
4411 }
The Android Open Source Project10592532009-03-18 17:39:46 -07004412 }
4413 }
4414 }
4415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416
Kenny Root447106f2011-03-23 11:00:15 -07004417 if (pkg.mAdoptPermissions != null) {
4418 // This package wants to adopt ownership of permissions from
4419 // another package.
4420 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
4421 final String origName = pkg.mAdoptPermissions.get(i);
4422 final PackageSetting orig = mSettings.peekPackageLPr(origName);
4423 if (orig != null) {
4424 if (verifyPackageUpdateLPr(orig, pkg)) {
4425 Slog.i(TAG, "Adopting permissions from " + origName + " to "
4426 + pkg.packageName);
4427 mSettings.transferPermissionsLPw(origName, pkg.packageName);
4428 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004429 }
4430 }
4431 }
4432 }
Kenny Root447106f2011-03-23 11:00:15 -07004433
4434 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004435
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004436 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 pkg.applicationInfo.processName = fixProcessName(
4439 pkg.applicationInfo.packageName,
4440 pkg.applicationInfo.processName,
4441 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442
4443 File dataPath;
4444 if (mPlatformPackage == pkg) {
4445 // The system package is special.
4446 dataPath = new File (Environment.getDataDirectory(), "system");
4447 pkg.applicationInfo.dataDir = dataPath.getPath();
4448 } else {
4449 // This is a normal package, need to make its data directory.
Dave Burke383fa182012-10-23 23:12:19 -07004450 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07004451
Dave Burke383fa182012-10-23 23:12:19 -07004452 boolean uidError = false;
4453
4454 if (dataPath.exists()) {
4455 int currentUid = 0;
4456 try {
4457 StructStat stat = Libcore.os.stat(dataPath.getPath());
4458 currentUid = stat.st_uid;
4459 } catch (ErrnoException e) {
4460 Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004462
Dave Burke383fa182012-10-23 23:12:19 -07004463 // If we have mismatched owners for the data path, we have a problem.
4464 if (currentUid != pkg.applicationInfo.uid) {
4465 boolean recovered = false;
4466 if (currentUid == 0) {
4467 // The directory somehow became owned by root. Wow.
4468 // This is probably because the system was stopped while
4469 // installd was in the middle of messing with its libs
4470 // directory. Ask installd to fix that.
4471 int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
4472 pkg.applicationInfo.uid);
4473 if (ret >= 0) {
4474 recovered = true;
4475 String msg = "Package " + pkg.packageName
4476 + " unexpectedly changed to uid 0; recovered to " +
4477 + pkg.applicationInfo.uid;
4478 reportSettingsProblem(Log.WARN, msg);
4479 }
4480 }
4481 if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
4482 || (scanMode&SCAN_BOOTING) != 0)) {
4483 // If this is a system app, we can at least delete its
4484 // current data so the application will still work.
4485 int ret = removeDataDirsLI(pkgName);
4486 if (ret >= 0) {
4487 // TODO: Kill the processes first
4488 // Old data gone!
4489 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
4490 ? "System package " : "Third party package ";
4491 String msg = prefix + pkg.packageName
4492 + " has changed from uid: "
4493 + currentUid + " to "
4494 + pkg.applicationInfo.uid + "; old data erased";
4495 reportSettingsProblem(Log.WARN, msg);
4496 recovered = true;
4497
4498 // And now re-install the app.
Robert Craig0f40dc92013-03-25 06:33:03 -04004499 ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
4500 pkg.applicationInfo.seinfo);
Dave Burke383fa182012-10-23 23:12:19 -07004501 if (ret == -1) {
4502 // Ack should not happen!
4503 msg = prefix + pkg.packageName
4504 + " could not have data directory re-created after delete.";
4505 reportSettingsProblem(Log.WARN, msg);
4506 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4507 return null;
4508 }
4509 }
4510 if (!recovered) {
4511 mHasSystemUidErrors = true;
4512 }
4513 } else if (!recovered) {
4514 // If we allow this install to proceed, we will be broken.
4515 // Abort, abort!
4516 mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED;
4517 return null;
4518 }
4519 if (!recovered) {
4520 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
4521 + pkg.applicationInfo.uid + "/fs_"
4522 + currentUid;
4523 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
4524 String msg = "Package " + pkg.packageName
4525 + " has mismatched uid: "
4526 + currentUid + " on disk, "
4527 + pkg.applicationInfo.uid + " in settings";
4528 // writer
4529 synchronized (mPackages) {
4530 mSettings.mReadMessages.append(msg);
4531 mSettings.mReadMessages.append('\n');
4532 uidError = true;
4533 if (!pkgSetting.uidError) {
4534 reportSettingsProblem(Log.ERROR, msg);
4535 }
4536 }
4537 }
4538 }
Kenny Root4525f5b2012-10-22 14:24:23 -07004539 pkg.applicationInfo.dataDir = dataPath.getPath();
Dave Burke383fa182012-10-23 23:12:19 -07004540 } else {
4541 if (DEBUG_PACKAGE_SCANNING) {
4542 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4543 Log.v(TAG, "Want this data dir: " + dataPath);
4544 }
Nick Kralevich15069212013-01-09 15:54:56 -08004545 //invoke installer to do the actual installation
Robert Craig0f40dc92013-03-25 06:33:03 -04004546 int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
4547 pkg.applicationInfo.seinfo);
Dave Burke383fa182012-10-23 23:12:19 -07004548 if (ret < 0) {
4549 // Error from installer
4550 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4551 return null;
4552 }
4553
4554 if (dataPath.exists()) {
4555 pkg.applicationInfo.dataDir = dataPath.getPath();
4556 } else {
4557 Slog.w(TAG, "Unable to create data directory: " + dataPath);
4558 pkg.applicationInfo.dataDir = null;
4559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 }
Kenny Root85387d72010-08-26 10:13:11 -07004561
4562 /*
Dave Burke383fa182012-10-23 23:12:19 -07004563 * Set the data dir to the default "/data/data/<package name>/lib"
4564 * if we got here without anyone telling us different (e.g., apps
4565 * stored on SD card have their native libraries stored in the ASEC
4566 * container with the APK).
4567 *
4568 * This happens during an upgrade from a package settings file that
4569 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07004570 */
Dave Burke383fa182012-10-23 23:12:19 -07004571 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
Kenny Rootbd135c12010-10-05 12:26:27 -07004572 if (pkgSetting.nativeLibraryPathString == null) {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004573 setInternalAppNativeLibraryPath(pkg, pkgSetting);
Kenny Rootbd135c12010-10-05 12:26:27 -07004574 } else {
4575 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
4576 }
Kenny Root85387d72010-08-26 10:13:11 -07004577 }
Dave Burke383fa182012-10-23 23:12:19 -07004578
4579 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 }
4581
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004582 String path = scanFile.getPath();
4583 /* Note: We don't want to unpack the native binaries for
4584 * system applications, unless they have been updated
4585 * (the binaries are already under /system/lib).
4586 * Also, don't unpack libs for apps on the external card
4587 * since they should have their libraries in the ASEC
4588 * container already.
4589 *
4590 * In other words, we're going to unpack the binaries
4591 * only for non-system apps and system app upgrades.
4592 */
4593 if (pkg.applicationInfo.nativeLibraryDir != null) {
4594 try {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004595 File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
Kenny Root5832ead2011-08-02 15:47:08 -07004596 final String dataPathString = dataPath.getCanonicalPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07004597
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004598 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
4599 /*
4600 * Upgrading from a previous version of the OS sometimes
4601 * leaves native libraries in the /data/data/<app>/lib
4602 * directory for system apps even when they shouldn't be.
4603 * Recent changes in the JNI library search path
4604 * necessitates we remove those to match previous behavior.
4605 */
4606 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
4607 Log.i(TAG, "removed obsolete native libraries for system package "
4608 + path);
Kenny Root831baa22010-10-05 12:29:25 -07004609 }
Kenny Roota3e90792012-10-18 10:58:36 -07004610 } else {
4611 if (!isForwardLocked(pkg) && !isExternal(pkg)) {
4612 /*
4613 * Update native library dir if it starts with
4614 * /data/data
4615 */
4616 if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
4617 setInternalAppNativeLibraryPath(pkg, pkgSetting);
4618 nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
4619 }
Kenny Root66269ea2011-07-12 14:14:01 -07004620
Kenny Roota3e90792012-10-18 10:58:36 -07004621 try {
4622 if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
4623 Slog.e(TAG, "Unable to copy native libraries");
4624 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4625 return null;
4626 }
4627 } catch (IOException e) {
4628 Slog.e(TAG, "Unable to copy native libraries", e);
Kenny Rootddbe50d2012-09-06 13:18:37 -07004629 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4630 return null;
4631 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07004632 }
4633
Dianne Hackborn40e9f292012-11-27 19:12:23 -08004634 if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
Kenny Roota3e90792012-10-18 10:58:36 -07004635 final int[] userIds = sUserManager.getUserIds();
4636 synchronized (mInstallLock) {
4637 for (int userId : userIds) {
4638 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
4639 pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
4640 Slog.w(TAG, "Failed linking native library dir (user=" + userId
4641 + ")");
4642 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4643 return null;
4644 }
4645 }
Nick Kralevich7de350a2012-09-07 15:48:11 -07004646 }
Kenny Root831baa22010-10-05 12:29:25 -07004647 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004648 } catch (IOException ioe) {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004649 Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004651 }
4652 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004653
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004654 if ((scanMode&SCAN_NO_DEX) == 0) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07004655 if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
Dianne Hackborn661cd522011-08-22 00:26:20 -07004656 == DEX_OPT_FAILED) {
Narayan Kamath65048bd2013-12-16 18:18:12 +00004657 if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
4658 removeDataDirsLI(pkg.packageName);
4659 }
4660
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004661 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
4662 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 }
4664 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 if (mFactoryTest && pkg.requestedPermissions.contains(
4667 android.Manifest.permission.FACTORY_TEST)) {
4668 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
4669 }
4670
Dianne Hackbornc895be72013-03-11 17:48:43 -07004671 ArrayList<PackageParser.Package> clientLibPkgs = null;
4672
4673 // writer
4674 synchronized (mPackages) {
4675 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
4676 // Only system apps can add new shared libraries.
4677 if (pkg.libraryNames != null) {
4678 for (int i=0; i<pkg.libraryNames.size(); i++) {
4679 String name = pkg.libraryNames.get(i);
4680 boolean allowed = false;
4681 if (isUpdatedSystemApp(pkg)) {
4682 // New library entries can only be added through the
4683 // system image. This is important to get rid of a lot
4684 // of nasty edge cases: for example if we allowed a non-
4685 // system update of the app to add a library, then uninstalling
4686 // the update would make the library go away, and assumptions
4687 // we made such as through app install filtering would now
4688 // have allowed apps on the device which aren't compatible
4689 // with it. Better to just have the restriction here, be
4690 // conservative, and create many fewer cases that can negatively
4691 // impact the user experience.
4692 final PackageSetting sysPs = mSettings
4693 .getDisabledSystemPkgLPr(pkg.packageName);
4694 if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
4695 for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
4696 if (name.equals(sysPs.pkg.libraryNames.get(j))) {
4697 allowed = true;
4698 allowed = true;
4699 break;
4700 }
4701 }
4702 }
4703 } else {
4704 allowed = true;
4705 }
4706 if (allowed) {
4707 if (!mSharedLibraries.containsKey(name)) {
4708 mSharedLibraries.put(name, new SharedLibraryEntry(null,
4709 pkg.packageName));
4710 } else if (!name.equals(pkg.packageName)) {
4711 Slog.w(TAG, "Package " + pkg.packageName + " library "
4712 + name + " already exists; skipping");
4713 }
4714 } else {
4715 Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
4716 + name + " that is not declared on system image; skipping");
4717 }
4718 }
4719 if ((scanMode&SCAN_BOOTING) == 0) {
4720 // If we are not booting, we need to update any applications
4721 // that are clients of our shared library. If we are booting,
4722 // this will all be done once the scan is complete.
4723 clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
4724 }
4725 }
4726 }
4727 }
4728
4729 // We also need to dexopt any apps that are dependent on this library. Note that
4730 // if these fail, we should abort the install since installing the library will
4731 // result in some apps being broken.
4732 if (clientLibPkgs != null) {
4733 if ((scanMode&SCAN_NO_DEX) == 0) {
4734 for (int i=0; i<clientLibPkgs.size(); i++) {
4735 PackageParser.Package clientPkg = clientLibPkgs.get(i);
4736 if (performDexOptLI(clientPkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
4737 == DEX_OPT_FAILED) {
Narayan Kamath65048bd2013-12-16 18:18:12 +00004738 if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
4739 removeDataDirsLI(pkg.packageName);
4740 }
4741
Dianne Hackbornc895be72013-03-11 17:48:43 -07004742 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
4743 return null;
4744 }
4745 }
4746 }
4747 }
4748
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004749 // Request the ActivityManager to kill the process(only for existing packages)
4750 // so that we do not end up in a confused state while the user is still using the older
4751 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004752 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Christopher Tated15967482013-10-04 13:57:22 -07004753 // If the package lives in an asec, tell everyone that the container is going
4754 // away so they can clean up any references to its resources (which would prevent
4755 // vold from being able to unmount the asec)
4756 if (isForwardLocked(pkg) || isExternal(pkg)) {
4757 if (DEBUG_INSTALL) {
4758 Slog.i(TAG, "upgrading pkg " + pkg + " is ASEC-hosted -> UNAVAILABLE");
4759 }
4760 final int[] uidArray = new int[] { pkg.applicationInfo.uid };
4761 final ArrayList<String> pkgList = new ArrayList<String>(1);
4762 pkgList.add(pkg.applicationInfo.packageName);
4763 sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
4764 }
4765
4766 // Post the request that it be killed now that the going-away broadcast is en route
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004767 killApplication(pkg.applicationInfo.packageName,
Dianne Hackborn21d9b562013-05-28 17:46:59 -07004768 pkg.applicationInfo.uid, "update pkg");
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004769 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004770
Dianne Hackbornc895be72013-03-11 17:48:43 -07004771 // Also need to kill any apps that are dependent on the library.
4772 if (clientLibPkgs != null) {
4773 for (int i=0; i<clientLibPkgs.size(); i++) {
4774 PackageParser.Package clientPkg = clientLibPkgs.get(i);
4775 killApplication(clientPkg.applicationInfo.packageName,
Dianne Hackborn21d9b562013-05-28 17:46:59 -07004776 clientPkg.applicationInfo.uid, "update lib");
Dianne Hackbornc895be72013-03-11 17:48:43 -07004777 }
4778 }
4779
Kenny Root447106f2011-03-23 11:00:15 -07004780 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004781 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004782 // We don't expect installation to fail beyond this point,
4783 if ((scanMode&SCAN_MONITOR) != 0) {
4784 mAppDirs.put(pkg.mPath, pkg);
4785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07004787 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004789 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004790 // Make sure we don't accidentally delete its data.
Jeff Sharkey752cd922012-09-23 16:25:12 -07004791 final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
4792 while (iter.hasNext()) {
4793 PackageCleanItem item = iter.next();
4794 if (pkgName.equals(item.packageName)) {
4795 iter.remove();
4796 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004797 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07004798
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004799 // Take care of first install / last update times.
4800 if (currentTime != 0) {
4801 if (pkgSetting.firstInstallTime == 0) {
4802 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
4803 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
4804 pkgSetting.lastUpdateTime = currentTime;
4805 }
4806 } else if (pkgSetting.firstInstallTime == 0) {
4807 // We need *something*. Take time time stamp of the file.
4808 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
4809 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
4810 if (scanFileTime != pkgSetting.timeStamp) {
4811 // A package on the system image has changed; consider this
4812 // to be an update.
4813 pkgSetting.lastUpdateTime = scanFileTime;
4814 }
4815 }
4816
Geremy Condraf1bcca82013-01-07 22:35:24 -08004817 // Add the package's KeySets to the global KeySetManager
4818 KeySetManager ksm = mSettings.mKeySetManager;
4819 try {
4820 ksm.addSigningKeySetToPackage(pkg.packageName, pkg.mSigningKeys);
4821 if (pkg.mKeySetMapping != null) {
4822 for (Map.Entry<String, Set<PublicKey>> entry : pkg.mKeySetMapping.entrySet()) {
4823 if (entry.getValue() != null) {
4824 ksm.addDefinedKeySetToPackage(pkg.packageName,
4825 entry.getValue(), entry.getKey());
4826 }
4827 }
4828 }
4829 } catch (NullPointerException e) {
4830 Slog.e(TAG, "Could not add KeySet to " + pkg.packageName, e);
4831 } catch (IllegalArgumentException e) {
4832 Slog.e(TAG, "Could not add KeySet to malformed package" + pkg.packageName, e);
4833 }
4834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 int N = pkg.providers.size();
4836 StringBuilder r = null;
4837 int i;
4838 for (i=0; i<N; i++) {
4839 PackageParser.Provider p = pkg.providers.get(i);
4840 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
4841 p.info.processName, pkg.applicationInfo.uid);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004842 mProviders.addProvider(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004843 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004844 if (p.info.authority != null) {
4845 String names[] = p.info.authority.split(";");
4846 p.info.authority = null;
4847 for (int j = 0; j < names.length; j++) {
4848 if (j == 1 && p.syncable) {
4849 // We only want the first authority for a provider to possibly be
4850 // syncable, so if we already added this provider using a different
4851 // authority clear the syncable flag. We copy the provider before
4852 // changing it because the mProviders object contains a reference
4853 // to a provider that we don't want to change.
4854 // Only do this for the second authority since the resulting provider
4855 // object can be the same for all future authorities for this provider.
4856 p = new PackageParser.Provider(p);
4857 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004859 if (!mProvidersByAuthority.containsKey(names[j])) {
4860 mProvidersByAuthority.put(names[j], p);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004861 if (p.info.authority == null) {
4862 p.info.authority = names[j];
4863 } else {
4864 p.info.authority = p.info.authority + ";" + names[j];
4865 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004866 if (DEBUG_PACKAGE_SCANNING) {
4867 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4868 Log.d(TAG, "Registered content provider: " + names[j]
4869 + ", className = " + p.info.name + ", isSyncable = "
4870 + p.info.isSyncable);
4871 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004872 } else {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004873 PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004874 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004875 " (in package " + pkg.applicationInfo.packageName +
4876 "): name already used by "
4877 + ((other != null && other.getComponentName() != null)
4878 ? other.getComponentName().getPackageName() : "?"));
4879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 }
4881 }
4882 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4883 if (r == null) {
4884 r = new StringBuilder(256);
4885 } else {
4886 r.append(' ');
4887 }
4888 r.append(p.info.name);
4889 }
4890 }
4891 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004892 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 N = pkg.services.size();
4896 r = null;
4897 for (i=0; i<N; i++) {
4898 PackageParser.Service s = pkg.services.get(i);
4899 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
4900 s.info.processName, pkg.applicationInfo.uid);
4901 mServices.addService(s);
4902 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4903 if (r == null) {
4904 r = new StringBuilder(256);
4905 } else {
4906 r.append(' ');
4907 }
4908 r.append(s.info.name);
4909 }
4910 }
4911 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004912 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 N = pkg.receivers.size();
4916 r = null;
4917 for (i=0; i<N; i++) {
4918 PackageParser.Activity a = pkg.receivers.get(i);
4919 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4920 a.info.processName, pkg.applicationInfo.uid);
4921 mReceivers.addActivity(a, "receiver");
4922 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4923 if (r == null) {
4924 r = new StringBuilder(256);
4925 } else {
4926 r.append(' ');
4927 }
4928 r.append(a.info.name);
4929 }
4930 }
4931 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004932 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 N = pkg.activities.size();
4936 r = null;
4937 for (i=0; i<N; i++) {
4938 PackageParser.Activity a = pkg.activities.get(i);
4939 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4940 a.info.processName, pkg.applicationInfo.uid);
4941 mActivities.addActivity(a, "activity");
4942 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4943 if (r == null) {
4944 r = new StringBuilder(256);
4945 } else {
4946 r.append(' ');
4947 }
4948 r.append(a.info.name);
4949 }
4950 }
4951 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004952 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 N = pkg.permissionGroups.size();
4956 r = null;
4957 for (i=0; i<N; i++) {
4958 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
4959 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
4960 if (cur == null) {
4961 mPermissionGroups.put(pg.info.name, pg);
4962 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4963 if (r == null) {
4964 r = new StringBuilder(256);
4965 } else {
4966 r.append(' ');
4967 }
4968 r.append(pg.info.name);
4969 }
4970 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004971 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 + pg.info.packageName + " ignored: original from "
4973 + cur.info.packageName);
4974 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4975 if (r == null) {
4976 r = new StringBuilder(256);
4977 } else {
4978 r.append(' ');
4979 }
4980 r.append("DUP:");
4981 r.append(pg.info.name);
4982 }
4983 }
4984 }
4985 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004986 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 N = pkg.permissions.size();
4990 r = null;
4991 for (i=0; i<N; i++) {
4992 PackageParser.Permission p = pkg.permissions.get(i);
4993 HashMap<String, BasePermission> permissionMap =
4994 p.tree ? mSettings.mPermissionTrees
4995 : mSettings.mPermissions;
4996 p.group = mPermissionGroups.get(p.info.group);
4997 if (p.info.group == null || p.group != null) {
4998 BasePermission bp = permissionMap.get(p.info.name);
4999 if (bp == null) {
5000 bp = new BasePermission(p.info.name, p.info.packageName,
5001 BasePermission.TYPE_NORMAL);
5002 permissionMap.put(p.info.name, bp);
5003 }
5004 if (bp.perm == null) {
Christopher Tate3aeea1f2013-11-05 12:28:10 -08005005 if (bp.sourcePackage != null
5006 && !bp.sourcePackage.equals(p.info.packageName)) {
5007 // If this is a permission that was formerly defined by a non-system
5008 // app, but is now defined by a system app (following an upgrade),
5009 // discard the previous declaration and consider the system's to be
5010 // canonical.
5011 if (isSystemApp(p.owner)) {
Christopher Tate08af7332014-01-07 16:05:22 -08005012 String msg = "New decl " + p.owner + " of permission "
5013 + p.info.name + " is system";
5014 reportSettingsProblem(Log.WARN, msg);
Christopher Tate3aeea1f2013-11-05 12:28:10 -08005015 bp.sourcePackage = null;
5016 }
5017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 if (bp.sourcePackage == null
5019 || bp.sourcePackage.equals(p.info.packageName)) {
5020 BasePermission tree = findPermissionTreeLP(p.info.name);
5021 if (tree == null
5022 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005023 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 bp.perm = p;
5025 bp.uid = pkg.applicationInfo.uid;
5026 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
5027 if (r == null) {
5028 r = new StringBuilder(256);
5029 } else {
5030 r.append(' ');
5031 }
5032 r.append(p.info.name);
5033 }
5034 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005035 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 + p.info.packageName + " ignored: base tree "
5037 + tree.name + " is from package "
5038 + tree.sourcePackage);
5039 }
5040 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005041 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 + p.info.packageName + " ignored: original from "
5043 + bp.sourcePackage);
5044 }
5045 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
5046 if (r == null) {
5047 r = new StringBuilder(256);
5048 } else {
5049 r.append(' ');
5050 }
5051 r.append("DUP:");
5052 r.append(p.info.name);
5053 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005054 if (bp.perm == p) {
5055 bp.protectionLevel = p.info.protectionLevel;
5056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005058 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 + p.info.packageName + " ignored: no group "
5060 + p.group);
5061 }
5062 }
5063 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08005064 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 N = pkg.instrumentation.size();
5068 r = null;
5069 for (i=0; i<N; i++) {
5070 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
5071 a.info.packageName = pkg.applicationInfo.packageName;
5072 a.info.sourceDir = pkg.applicationInfo.sourceDir;
5073 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
5074 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07005075 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005076 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
5078 if (r == null) {
5079 r = new StringBuilder(256);
5080 } else {
5081 r.append(' ');
5082 }
5083 r.append(a.info.name);
5084 }
5085 }
5086 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08005087 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005088 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005089
Dianne Hackborn854060af2009-07-09 18:14:31 -07005090 if (pkg.protectedBroadcasts != null) {
5091 N = pkg.protectedBroadcasts.size();
5092 for (i=0; i<N; i++) {
5093 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
5094 }
5095 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 pkgSetting.setTimeStamp(scanFileTime);
5098 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 return pkg;
5101 }
5102
Jose Limabb9682e2013-08-16 16:14:32 -07005103 private void setUpCustomResolverActivity(PackageParser.Package pkg) {
5104 synchronized (mPackages) {
5105 mResolverReplaced = true;
5106 // Set up information for custom user intent resolution activity.
5107 mResolveActivity.applicationInfo = pkg.applicationInfo;
5108 mResolveActivity.name = mCustomResolverComponentName.getClassName();
5109 mResolveActivity.packageName = pkg.applicationInfo.packageName;
5110 mResolveActivity.processName = null;
5111 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
5112 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
5113 ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
5114 mResolveActivity.theme = 0;
5115 mResolveActivity.exported = true;
5116 mResolveActivity.enabled = true;
5117 mResolveInfo.activityInfo = mResolveActivity;
5118 mResolveInfo.priority = 0;
5119 mResolveInfo.preferredOrder = 0;
5120 mResolveInfo.match = 0;
5121 mResolveComponentName = mCustomResolverComponentName;
5122 Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " +
5123 mResolveComponentName);
5124 }
5125 }
5126
Kenny Rootddbe50d2012-09-06 13:18:37 -07005127 private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
5128 PackageSetting pkgSetting) {
5129 final String apkLibPath = getApkName(pkgSetting.codePathString);
5130 final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
5131 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
5132 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
5133 }
5134
5135 private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
5136 throws IOException {
5137 if (!nativeLibraryDir.isDirectory()) {
5138 nativeLibraryDir.delete();
Kenny Root9bbd70a2012-09-10 11:13:36 -07005139
Kenny Rootddbe50d2012-09-06 13:18:37 -07005140 if (!nativeLibraryDir.mkdir()) {
5141 throw new IOException("Cannot create " + nativeLibraryDir.getPath());
5142 }
Kenny Root9bbd70a2012-09-10 11:13:36 -07005143
Kenny Rootddbe50d2012-09-06 13:18:37 -07005144 try {
5145 Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
5146 | S_IXOTH);
5147 } catch (ErrnoException e) {
5148 throw new IOException("Cannot chmod native library directory "
5149 + nativeLibraryDir.getPath(), e);
5150 }
Kenny Root9bbd70a2012-09-10 11:13:36 -07005151 } else if (!SELinux.restorecon(nativeLibraryDir)) {
5152 throw new IOException("Cannot set SELinux context for " + nativeLibraryDir.getPath());
Kenny Rootddbe50d2012-09-06 13:18:37 -07005153 }
5154
5155 /*
5156 * If this is an internal application or our nativeLibraryPath points to
5157 * the app-lib directory, unpack the libraries if necessary.
5158 */
5159 return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
5160 }
5161
Dianne Hackborn21d9b562013-05-28 17:46:59 -07005162 private void killApplication(String pkgName, int appId, String reason) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005163 // Request the ActivityManager to kill the process(only for existing packages)
5164 // so that we do not end up in a confused state while the user is still using the older
5165 // version of the application while the new one gets installed.
5166 IActivityManager am = ActivityManagerNative.getDefault();
5167 if (am != null) {
5168 try {
Dianne Hackborn21d9b562013-05-28 17:46:59 -07005169 am.killApplicationWithAppId(pkgName, appId, reason);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005170 } catch (RemoteException e) {
5171 }
5172 }
5173 }
5174
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005175 void removePackageLI(PackageSetting ps, boolean chatty) {
5176 if (DEBUG_INSTALL) {
5177 if (chatty)
5178 Log.d(TAG, "Removing package " + ps.name);
5179 }
5180
5181 // writer
5182 synchronized (mPackages) {
5183 mPackages.remove(ps.name);
5184 if (ps.codePathString != null) {
5185 mAppDirs.remove(ps.codePathString);
5186 }
5187
5188 final PackageParser.Package pkg = ps.pkg;
5189 if (pkg != null) {
5190 cleanPackageDataStructuresLILPw(pkg, chatty);
5191 }
5192 }
5193 }
5194
5195 void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08005196 if (DEBUG_INSTALL) {
5197 if (chatty)
5198 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
5199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200
Kenny Root447106f2011-03-23 11:00:15 -07005201 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 mPackages.remove(pkg.applicationInfo.packageName);
5204 if (pkg.mPath != null) {
5205 mAppDirs.remove(pkg.mPath);
5206 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005207 cleanPackageDataStructuresLILPw(pkg, chatty);
5208 }
5209 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005210
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005211 void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
5212 int N = pkg.providers.size();
5213 StringBuilder r = null;
5214 int i;
5215 for (i=0; i<N; i++) {
5216 PackageParser.Provider p = pkg.providers.get(i);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005217 mProviders.removeProvider(p);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005218 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005219
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005220 /* There was another ContentProvider with this authority when
5221 * this app was installed so this authority is null,
5222 * Ignore it as we don't have to unregister the provider.
5223 */
5224 continue;
5225 }
5226 String names[] = p.info.authority.split(";");
5227 for (int j = 0; j < names.length; j++) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005228 if (mProvidersByAuthority.get(names[j]) == p) {
5229 mProvidersByAuthority.remove(names[j]);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005230 if (DEBUG_REMOVE) {
5231 if (chatty)
5232 Log.d(TAG, "Unregistered content provider: " + names[j]
5233 + ", className = " + p.info.name + ", isSyncable = "
5234 + p.info.isSyncable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 }
5236 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005237 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07005238 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005239 if (r == null) {
5240 r = new StringBuilder(256);
5241 } else {
5242 r.append(' ');
5243 }
5244 r.append(p.info.name);
5245 }
5246 }
5247 if (r != null) {
5248 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
5249 }
5250
5251 N = pkg.services.size();
5252 r = null;
5253 for (i=0; i<N; i++) {
5254 PackageParser.Service s = pkg.services.get(i);
5255 mServices.removeService(s);
5256 if (chatty) {
5257 if (r == null) {
5258 r = new StringBuilder(256);
5259 } else {
5260 r.append(' ');
5261 }
5262 r.append(s.info.name);
5263 }
5264 }
5265 if (r != null) {
5266 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
5267 }
5268
5269 N = pkg.receivers.size();
5270 r = null;
5271 for (i=0; i<N; i++) {
5272 PackageParser.Activity a = pkg.receivers.get(i);
5273 mReceivers.removeActivity(a, "receiver");
Dianne Hackbornc895be72013-03-11 17:48:43 -07005274 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005275 if (r == null) {
5276 r = new StringBuilder(256);
5277 } else {
5278 r.append(' ');
5279 }
5280 r.append(a.info.name);
5281 }
5282 }
5283 if (r != null) {
5284 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
5285 }
5286
5287 N = pkg.activities.size();
5288 r = null;
5289 for (i=0; i<N; i++) {
5290 PackageParser.Activity a = pkg.activities.get(i);
5291 mActivities.removeActivity(a, "activity");
Dianne Hackbornc895be72013-03-11 17:48:43 -07005292 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005293 if (r == null) {
5294 r = new StringBuilder(256);
5295 } else {
5296 r.append(' ');
5297 }
5298 r.append(a.info.name);
5299 }
5300 }
5301 if (r != null) {
5302 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
5303 }
5304
5305 N = pkg.permissions.size();
5306 r = null;
5307 for (i=0; i<N; i++) {
5308 PackageParser.Permission p = pkg.permissions.get(i);
5309 BasePermission bp = mSettings.mPermissions.get(p.info.name);
5310 if (bp == null) {
5311 bp = mSettings.mPermissionTrees.get(p.info.name);
5312 }
5313 if (bp != null && bp.perm == p) {
5314 bp.perm = null;
Dianne Hackbornc895be72013-03-11 17:48:43 -07005315 if (DEBUG_REMOVE && chatty) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 if (r == null) {
5317 r = new StringBuilder(256);
5318 } else {
5319 r.append(' ');
5320 }
5321 r.append(p.info.name);
5322 }
5323 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005324 }
5325 if (r != null) {
5326 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
5327 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005328
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005329 N = pkg.instrumentation.size();
5330 r = null;
5331 for (i=0; i<N; i++) {
5332 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
5333 mInstrumentation.remove(a.getComponentName());
Dianne Hackbornc895be72013-03-11 17:48:43 -07005334 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005335 if (r == null) {
5336 r = new StringBuilder(256);
5337 } else {
5338 r.append(' ');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005339 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005340 r.append(a.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005342 }
5343 if (r != null) {
5344 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07005346
5347 r = null;
5348 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5349 // Only system apps can hold shared libraries.
5350 if (pkg.libraryNames != null) {
5351 for (i=0; i<pkg.libraryNames.size(); i++) {
5352 String name = pkg.libraryNames.get(i);
5353 SharedLibraryEntry cur = mSharedLibraries.get(name);
5354 if (cur != null && cur.apk != null && cur.apk.equals(pkg.packageName)) {
5355 mSharedLibraries.remove(name);
5356 if (DEBUG_REMOVE && chatty) {
5357 if (r == null) {
5358 r = new StringBuilder(256);
5359 } else {
5360 r.append(' ');
5361 }
5362 r.append(name);
5363 }
5364 }
5365 }
5366 }
5367 }
5368 if (r != null) {
5369 if (DEBUG_REMOVE) Log.d(TAG, " Libraries: " + r);
5370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005371 }
5372
5373 private static final boolean isPackageFilename(String name) {
5374 return name != null && name.endsWith(".apk");
5375 }
5376
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005377 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
5378 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
5379 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
5380 return true;
5381 }
5382 }
5383 return false;
5384 }
Dianne Hackborne639da72012-02-21 15:11:13 -08005385
5386 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
5387 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
5388 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
5389
Kenny Root447106f2011-03-23 11:00:15 -07005390 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborne639da72012-02-21 15:11:13 -08005391 PackageParser.Package pkgInfo, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07005393 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07005395 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005396 if (bp.packageSetting == null) {
5397 // We may not yet have parsed the package, so just see if
5398 // we still know about its settings.
5399 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
5400 }
5401 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005402 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 + " from package " + bp.sourcePackage);
5404 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005405 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
5406 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
5407 Slog.i(TAG, "Removing old permission tree: " + bp.name
5408 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08005409 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005410 it.remove();
5411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 }
5413 }
5414
5415 // Make sure all dynamic permissions have been assigned to a package,
5416 // and make sure there are no dangling permissions.
5417 it = mSettings.mPermissions.values().iterator();
5418 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07005419 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 if (bp.type == BasePermission.TYPE_DYNAMIC) {
5421 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
5422 + bp.name + " pkg=" + bp.sourcePackage
5423 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005424 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005425 final BasePermission tree = findPermissionTreeLP(bp.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07005426 if (tree != null && tree.perm != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005427 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 bp.perm = new PackageParser.Permission(tree.perm.owner,
5429 new PermissionInfo(bp.pendingInfo));
5430 bp.perm.info.packageName = tree.perm.info.packageName;
5431 bp.perm.info.name = bp.name;
5432 bp.uid = tree.uid;
5433 }
5434 }
5435 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005436 if (bp.packageSetting == null) {
5437 // We may not yet have parsed the package, so just see if
5438 // we still know about its settings.
5439 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
5440 }
5441 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005442 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 + " from package " + bp.sourcePackage);
5444 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005445 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
5446 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
5447 Slog.i(TAG, "Removing old permission: " + bp.name
5448 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08005449 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005450 it.remove();
5451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005452 }
5453 }
5454
5455 // Now update the permissions for all packages, in particular
5456 // replace the granted permissions of the system packages.
Dianne Hackborne639da72012-02-21 15:11:13 -08005457 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005458 for (PackageParser.Package pkg : mPackages.values()) {
5459 if (pkg != pkgInfo) {
Dianne Hackborne639da72012-02-21 15:11:13 -08005460 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005461 }
5462 }
5463 }
5464
5465 if (pkgInfo != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08005466 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 }
5468 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005469
Kenny Root447106f2011-03-23 11:00:15 -07005470 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
5471 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 if (ps == null) {
5473 return;
5474 }
5475 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08005476 HashSet<String> origPermissions = gp.grantedPermissions;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005477 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 if (replace) {
5480 ps.permissionsFixed = false;
5481 if (gp == ps) {
Dianne Hackborne639da72012-02-21 15:11:13 -08005482 origPermissions = new HashSet<String>(gp.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 gp.grantedPermissions.clear();
5484 gp.gids = mGlobalGids;
5485 }
5486 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 if (gp.gids == null) {
5489 gp.gids = mGlobalGids;
5490 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 final int N = pkg.requestedPermissions.size();
5493 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07005494 final String name = pkg.requestedPermissions.get(i);
Nick Kralevich1cd6c6e2013-03-18 12:56:33 -07005495 final boolean required = pkg.requestedPermissionsRequired.get(i);
Kenny Root447106f2011-03-23 11:00:15 -07005496 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08005497 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08005499 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 }
5501 }
Nick Kralevichdaae5412013-04-01 13:12:26 -07005502
5503 if (bp == null || bp.packageSetting == null) {
5504 Slog.w(TAG, "Unknown permission " + name
5505 + " in package " + pkg.packageName);
5506 continue;
5507 }
5508
5509 final String perm = bp.name;
5510 boolean allowed;
5511 boolean allowedSig = false;
5512 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
5513 if (level == PermissionInfo.PROTECTION_NORMAL
5514 || level == PermissionInfo.PROTECTION_DANGEROUS) {
Nick Kralevich60792852013-04-03 14:12:24 -07005515 // We grant a normal or dangerous permission if any of the following
5516 // are true:
5517 // 1) The permission is required
5518 // 2) The permission is optional, but was granted in the past
5519 // 3) The permission is optional, but was requested by an
5520 // app in /system (not /data)
5521 //
5522 // Otherwise, reject the permission.
5523 allowed = (required || origPermissions.contains(perm)
5524 || (isSystemApp(ps) && !isUpdatedSystemApp(ps)));
Nick Kralevichdaae5412013-04-01 13:12:26 -07005525 } else if (bp.packageSetting == null) {
5526 // This permission is invalid; skip it.
5527 allowed = false;
5528 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
Nick Kralevich94b8c932013-04-02 09:27:27 -07005529 allowed = grantSignaturePermission(perm, pkg, bp, origPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 if (allowed) {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005531 allowedSig = true;
5532 }
5533 } else {
5534 allowed = false;
5535 }
5536 if (DEBUG_INSTALL) {
5537 if (gp != ps) {
5538 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
5539 }
5540 }
5541 if (allowed) {
Nick Kralevich60792852013-04-03 14:12:24 -07005542 if (!isSystemApp(ps) && ps.permissionsFixed) {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005543 // If this is an existing, non-system package, then
5544 // we can't add any new permissions to it.
5545 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005546 // Except... if this is a permission that was added
5547 // to the platform (note: need to only do this when
5548 // updating the platform).
Nick Kralevich3337dbf2013-04-01 13:27:30 -07005549 allowed = isNewPlatformPermissionForPackage(perm, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 }
Nick Kralevichdaae5412013-04-01 13:12:26 -07005551 }
5552 if (allowed) {
5553 if (!gp.grantedPermissions.contains(perm)) {
5554 changedPermission = true;
5555 gp.grantedPermissions.add(perm);
5556 gp.gids = appendInts(gp.gids, bp.gids);
5557 } else if (!ps.haveGids) {
5558 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 }
5560 } else {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005561 Slog.w(TAG, "Not granting permission " + perm
5562 + " to package " + pkg.packageName
5563 + " because it was previously installed without");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564 }
5565 } else {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005566 if (gp.grantedPermissions.remove(perm)) {
5567 changedPermission = true;
5568 gp.gids = removeInts(gp.gids, bp.gids);
5569 Slog.i(TAG, "Un-granting permission " + perm
5570 + " from package " + pkg.packageName
5571 + " (protectionLevel=" + bp.protectionLevel
5572 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
5573 + ")");
5574 } else {
5575 Slog.w(TAG, "Not granting permission " + perm
5576 + " to package " + pkg.packageName
5577 + " (protectionLevel=" + bp.protectionLevel
5578 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
5579 + ")");
5580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 }
5582 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005583
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005584 if ((changedPermission || replace) && !ps.permissionsFixed &&
Nick Kralevich60792852013-04-03 14:12:24 -07005585 !isSystemApp(ps) || isUpdatedSystemApp(ps)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 // This is the first that we have heard about this package, so the
5587 // permissions we have now selected are fixed until explicitly
5588 // changed.
5589 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07005591 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005592 }
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005593
Nick Kralevich3337dbf2013-04-01 13:27:30 -07005594 private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
5595 boolean allowed = false;
5596 final int NP = PackageParser.NEW_PERMISSIONS.length;
5597 for (int ip=0; ip<NP; ip++) {
5598 final PackageParser.NewPermissionInfo npi
5599 = PackageParser.NEW_PERMISSIONS[ip];
5600 if (npi.name.equals(perm)
5601 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
5602 allowed = true;
5603 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
5604 + pkg.packageName);
5605 break;
5606 }
5607 }
5608 return allowed;
5609 }
5610
Nick Kralevich94b8c932013-04-02 09:27:27 -07005611 private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005612 BasePermission bp, HashSet<String> origPermissions) {
5613 boolean allowed;
5614 allowed = (compareSignatures(
5615 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
5616 == PackageManager.SIGNATURE_MATCH)
5617 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
5618 == PackageManager.SIGNATURE_MATCH);
5619 if (!allowed && (bp.protectionLevel
5620 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
Christopher Tate072252c2013-07-29 14:20:15 -07005621 if (isSystemApp(pkg)) {
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005622 // For updated system applications, a system permission
5623 // is granted only if it had been defined by the original application.
5624 if (isUpdatedSystemApp(pkg)) {
5625 final PackageSetting sysPs = mSettings
5626 .getDisabledSystemPkgLPr(pkg.packageName);
5627 final GrantedPermissions origGp = sysPs.sharedUser != null
5628 ? sysPs.sharedUser : sysPs;
Christopher Tate072252c2013-07-29 14:20:15 -07005629
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005630 if (origGp.grantedPermissions.contains(perm)) {
Christopher Tate072252c2013-07-29 14:20:15 -07005631 // If the original was granted this permission, we take
5632 // that grant decision as read and propagate it to the
5633 // update.
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005634 allowed = true;
5635 } else {
5636 // The system apk may have been updated with an older
5637 // version of the one on the data partition, but which
5638 // granted a new system permission that it didn't have
5639 // before. In this case we do want to allow the app to
Christopher Tate628946a2013-10-18 18:11:05 -07005640 // now get the new permission if the ancestral apk is
5641 // privileged to get it.
5642 if (sysPs.pkg != null && sysPs.isPrivileged()) {
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005643 for (int j=0;
5644 j<sysPs.pkg.requestedPermissions.size(); j++) {
5645 if (perm.equals(
5646 sysPs.pkg.requestedPermissions.get(j))) {
5647 allowed = true;
5648 break;
5649 }
5650 }
5651 }
5652 }
5653 } else {
Christopher Tate072252c2013-07-29 14:20:15 -07005654 allowed = isPrivilegedApp(pkg);
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005655 }
5656 }
5657 }
5658 if (!allowed && (bp.protectionLevel
5659 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
5660 // For development permissions, a development permission
5661 // is granted only if it was already granted.
5662 allowed = origPermissions.contains(perm);
5663 }
5664 return allowed;
5665 }
5666
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08005667 final class ActivityIntentResolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07005669 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005670 boolean defaultOnly, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005671 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005673 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 }
5675
Amith Yamasani483f3b02012-03-13 16:08:00 -07005676 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
5677 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005678 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02005680 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005681 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683
Kenny Root60f7ad82011-03-22 12:49:06 -07005684 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005685 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005686 if (!sUserManager.exists(userId)) return null;
Mihai Predaeae850c2009-05-13 10:13:48 +02005687 if (packageActivities == null) {
5688 return null;
5689 }
5690 mFlags = flags;
5691 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08005692 final int N = packageActivities.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005693 ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
5694 new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02005695
5696 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02005697 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02005698 intentFilters = packageActivities.get(i).intents;
5699 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005700 PackageParser.ActivityIntentInfo[] array =
5701 new PackageParser.ActivityIntentInfo[intentFilters.size()];
5702 intentFilters.toArray(array);
5703 listCut.add(array);
Mihai Predac3320db2009-05-18 20:15:32 +02005704 }
Mihai Predaeae850c2009-05-13 10:13:48 +02005705 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07005706 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02005707 }
5708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08005710 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005711 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08005712 if (DEBUG_SHOW_INFO)
5713 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 TAG, " " + type + " " +
5715 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005716 if (DEBUG_SHOW_INFO)
5717 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08005718 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02005719 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08005721 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
5722 intent.setPriority(0);
5723 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
5724 + a.className + " with priority > 0, forcing to 0");
5725 }
Kenny Root9718cf52011-02-23 16:45:26 -08005726 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 Log.v(TAG, " IntentFilter:");
5728 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5729 }
5730 if (!intent.debugCheck()) {
5731 Log.w(TAG, "==> For Activity " + a.info.name);
5732 }
5733 addFilter(intent);
5734 }
5735 }
5736
5737 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005738 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08005739 if (DEBUG_SHOW_INFO) {
5740 Log.v(TAG, " " + type + " "
5741 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
5742 : a.info.name) + ":");
5743 Log.v(TAG, " Class=" + a.info.name);
5744 }
5745 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02005746 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005748 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 Log.v(TAG, " IntentFilter:");
5750 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5751 }
5752 removeFilter(intent);
5753 }
5754 }
5755
5756 @Override
5757 protected boolean allowFilterResult(
5758 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
5759 ActivityInfo filterAi = filter.activity.info;
5760 for (int i=dest.size()-1; i>=0; i--) {
5761 ActivityInfo destAi = dest.get(i).activityInfo;
5762 if (destAi.name == filterAi.name
5763 && destAi.packageName == filterAi.packageName) {
5764 return false;
5765 }
5766 }
5767 return true;
5768 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005771 protected ActivityIntentInfo[] newArray(int size) {
5772 return new ActivityIntentInfo[size];
5773 }
5774
5775 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005776 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005777 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005778 PackageParser.Package p = filter.activity.owner;
5779 if (p != null) {
5780 PackageSetting ps = (PackageSetting)p.mExtras;
5781 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005782 // System apps are never considered stopped for purposes of
5783 // filtering, because there may be no way for the user to
5784 // actually re-launch them.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005785 return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
5786 && ps.getStopped(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005787 }
5788 }
5789 return false;
5790 }
5791
5792 @Override
Ben Gruver4efe9402013-04-02 21:18:41 -07005793 protected boolean isPackageForFilter(String packageName,
5794 PackageParser.ActivityIntentInfo info) {
5795 return packageName.equals(info.activity.owner.packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005796 }
5797
5798 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005800 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005801 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005802 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 return null;
5804 }
5805 final PackageParser.Activity activity = info.activity;
5806 if (mSafeMode && (activity.info.applicationInfo.flags
5807 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5808 return null;
5809 }
Amith Yamasani13593602012-03-22 16:16:17 -07005810 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005811 if (ps == null) {
5812 return null;
5813 }
5814 ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
5815 ps.readUserState(userId), userId);
5816 if (ai == null) {
5817 return null;
5818 }
5819 final ResolveInfo res = new ResolveInfo();
5820 res.activityInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
5822 res.filter = info;
5823 }
5824 res.priority = info.getPriority();
5825 res.preferredOrder = activity.owner.mPreferredOrder;
5826 //System.out.println("Result: " + res.activityInfo.className +
5827 // " = " + res.priority);
5828 res.match = match;
5829 res.isDefault = info.hasDefault;
5830 res.labelRes = info.labelRes;
5831 res.nonLocalizedLabel = info.nonLocalizedLabel;
5832 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005833 res.system = isSystemApp(res.activityInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 return res;
5835 }
5836
5837 @Override
5838 protected void sortResults(List<ResolveInfo> results) {
5839 Collections.sort(results, mResolvePrioritySorter);
5840 }
5841
5842 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005843 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005845 out.print(prefix); out.print(
5846 Integer.toHexString(System.identityHashCode(filter.activity)));
5847 out.print(' ');
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005848 filter.activity.printComponentShortName(out);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005849 out.print(" filter ");
5850 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 }
5852
5853// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
5854// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
5855// final List<ResolveInfo> retList = Lists.newArrayList();
5856// while (i.hasNext()) {
5857// final ResolveInfo resolveInfo = i.next();
5858// if (isEnabledLP(resolveInfo.activityInfo)) {
5859// retList.add(resolveInfo);
5860// }
5861// }
5862// return retList;
5863// }
5864
5865 // Keys are String (activity class name), values are Activity.
5866 private final HashMap<ComponentName, PackageParser.Activity> mActivities
5867 = new HashMap<ComponentName, PackageParser.Activity>();
5868 private int mFlags;
5869 }
5870
5871 private final class ServiceIntentResolver
5872 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07005873 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005874 boolean defaultOnly, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005876 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 }
5878
Amith Yamasani483f3b02012-03-13 16:08:00 -07005879 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
5880 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005881 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005882 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02005883 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005884 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 }
5886
Kenny Root60f7ad82011-03-22 12:49:06 -07005887 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005888 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005889 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005890 if (packageServices == null) {
5891 return null;
5892 }
5893 mFlags = flags;
5894 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08005895 final int N = packageServices.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005896 ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
5897 new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005898
5899 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
5900 for (int i = 0; i < N; ++i) {
5901 intentFilters = packageServices.get(i).intents;
5902 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005903 PackageParser.ServiceIntentInfo[] array =
5904 new PackageParser.ServiceIntentInfo[intentFilters.size()];
5905 intentFilters.toArray(array);
5906 listCut.add(array);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005907 }
5908 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07005909 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005910 }
5911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005913 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08005914 if (DEBUG_SHOW_INFO) {
5915 Log.v(TAG, " "
5916 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005918 Log.v(TAG, " Class=" + s.info.name);
5919 }
5920 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 int j;
5922 for (j=0; j<NI; j++) {
5923 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005924 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 Log.v(TAG, " IntentFilter:");
5926 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5927 }
5928 if (!intent.debugCheck()) {
5929 Log.w(TAG, "==> For Service " + s.info.name);
5930 }
5931 addFilter(intent);
5932 }
5933 }
5934
5935 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005936 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08005937 if (DEBUG_SHOW_INFO) {
5938 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005940 Log.v(TAG, " Class=" + s.info.name);
5941 }
5942 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 int j;
5944 for (j=0; j<NI; j++) {
5945 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005946 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 Log.v(TAG, " IntentFilter:");
5948 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5949 }
5950 removeFilter(intent);
5951 }
5952 }
5953
5954 @Override
5955 protected boolean allowFilterResult(
5956 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
5957 ServiceInfo filterSi = filter.service.info;
5958 for (int i=dest.size()-1; i>=0; i--) {
5959 ServiceInfo destAi = dest.get(i).serviceInfo;
5960 if (destAi.name == filterSi.name
5961 && destAi.packageName == filterSi.packageName) {
5962 return false;
5963 }
5964 }
5965 return true;
5966 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005969 protected PackageParser.ServiceIntentInfo[] newArray(int size) {
5970 return new PackageParser.ServiceIntentInfo[size];
5971 }
5972
5973 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005974 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005975 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005976 PackageParser.Package p = filter.service.owner;
5977 if (p != null) {
5978 PackageSetting ps = (PackageSetting)p.mExtras;
5979 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005980 // System apps are never considered stopped for purposes of
5981 // filtering, because there may be no way for the user to
5982 // actually re-launch them.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005983 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
5984 && ps.getStopped(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005985 }
5986 }
5987 return false;
5988 }
5989
5990 @Override
Ben Gruver4efe9402013-04-02 21:18:41 -07005991 protected boolean isPackageForFilter(String packageName,
5992 PackageParser.ServiceIntentInfo info) {
5993 return packageName.equals(info.service.owner.packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005994 }
5995
5996 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005998 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005999 if (!sUserManager.exists(userId)) return null;
Jason parksa3cdaa52011-01-13 14:15:43 -06006000 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Amith Yamasani483f3b02012-03-13 16:08:00 -07006001 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 return null;
6003 }
6004 final PackageParser.Service service = info.service;
6005 if (mSafeMode && (service.info.applicationInfo.flags
6006 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6007 return null;
6008 }
Amith Yamasani13593602012-03-22 16:16:17 -07006009 PackageSetting ps = (PackageSetting) service.owner.mExtras;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006010 if (ps == null) {
6011 return null;
6012 }
6013 ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
6014 ps.readUserState(userId), userId);
Dianne Hackborn4428e172012-08-24 17:43:05 -07006015 if (si == null) {
6016 return null;
6017 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006018 final ResolveInfo res = new ResolveInfo();
6019 res.serviceInfo = si;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
6021 res.filter = filter;
6022 }
6023 res.priority = info.getPriority();
6024 res.preferredOrder = service.owner.mPreferredOrder;
6025 //System.out.println("Result: " + res.activityInfo.className +
6026 // " = " + res.priority);
6027 res.match = match;
6028 res.isDefault = info.hasDefault;
6029 res.labelRes = info.labelRes;
6030 res.nonLocalizedLabel = info.nonLocalizedLabel;
6031 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07006032 res.system = isSystemApp(res.serviceInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 return res;
6034 }
6035
6036 @Override
6037 protected void sortResults(List<ResolveInfo> results) {
6038 Collections.sort(results, mResolvePrioritySorter);
6039 }
6040
6041 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006042 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006044 out.print(prefix); out.print(
6045 Integer.toHexString(System.identityHashCode(filter.service)));
6046 out.print(' ');
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006047 filter.service.printComponentShortName(out);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006048 out.print(" filter ");
6049 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006050 }
6051
6052// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
6053// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
6054// final List<ResolveInfo> retList = Lists.newArrayList();
6055// while (i.hasNext()) {
6056// final ResolveInfo resolveInfo = (ResolveInfo) i;
6057// if (isEnabledLP(resolveInfo.serviceInfo)) {
6058// retList.add(resolveInfo);
6059// }
6060// }
6061// return retList;
6062// }
6063
6064 // Keys are String (activity class name), values are Activity.
6065 private final HashMap<ComponentName, PackageParser.Service> mServices
6066 = new HashMap<ComponentName, PackageParser.Service>();
6067 private int mFlags;
6068 };
6069
Jeff Sharkey85f5f812013-10-07 10:16:12 -07006070 private final class ProviderIntentResolver
6071 extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
6072 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
6073 boolean defaultOnly, int userId) {
6074 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
6075 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
6076 }
6077
6078 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
6079 int userId) {
6080 if (!sUserManager.exists(userId))
6081 return null;
6082 mFlags = flags;
6083 return super.queryIntent(intent, resolvedType,
6084 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
6085 }
6086
6087 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
6088 int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) {
6089 if (!sUserManager.exists(userId))
6090 return null;
6091 if (packageProviders == null) {
6092 return null;
6093 }
6094 mFlags = flags;
6095 final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
6096 final int N = packageProviders.size();
6097 ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
6098 new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
6099
6100 ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
6101 for (int i = 0; i < N; ++i) {
6102 intentFilters = packageProviders.get(i).intents;
6103 if (intentFilters != null && intentFilters.size() > 0) {
6104 PackageParser.ProviderIntentInfo[] array =
6105 new PackageParser.ProviderIntentInfo[intentFilters.size()];
6106 intentFilters.toArray(array);
6107 listCut.add(array);
6108 }
6109 }
6110 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
6111 }
6112
6113 public final void addProvider(PackageParser.Provider p) {
6114 mProviders.put(p.getComponentName(), p);
6115 if (DEBUG_SHOW_INFO) {
6116 Log.v(TAG, " "
6117 + (p.info.nonLocalizedLabel != null
6118 ? p.info.nonLocalizedLabel : p.info.name) + ":");
6119 Log.v(TAG, " Class=" + p.info.name);
6120 }
6121 final int NI = p.intents.size();
6122 int j;
6123 for (j = 0; j < NI; j++) {
6124 PackageParser.ProviderIntentInfo intent = p.intents.get(j);
6125 if (DEBUG_SHOW_INFO) {
6126 Log.v(TAG, " IntentFilter:");
6127 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
6128 }
6129 if (!intent.debugCheck()) {
6130 Log.w(TAG, "==> For Provider " + p.info.name);
6131 }
6132 addFilter(intent);
6133 }
6134 }
6135
6136 public final void removeProvider(PackageParser.Provider p) {
6137 mProviders.remove(p.getComponentName());
6138 if (DEBUG_SHOW_INFO) {
6139 Log.v(TAG, " " + (p.info.nonLocalizedLabel != null
6140 ? p.info.nonLocalizedLabel : p.info.name) + ":");
6141 Log.v(TAG, " Class=" + p.info.name);
6142 }
6143 final int NI = p.intents.size();
6144 int j;
6145 for (j = 0; j < NI; j++) {
6146 PackageParser.ProviderIntentInfo intent = p.intents.get(j);
6147 if (DEBUG_SHOW_INFO) {
6148 Log.v(TAG, " IntentFilter:");
6149 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
6150 }
6151 removeFilter(intent);
6152 }
6153 }
6154
6155 @Override
6156 protected boolean allowFilterResult(
6157 PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
6158 ProviderInfo filterPi = filter.provider.info;
6159 for (int i = dest.size() - 1; i >= 0; i--) {
6160 ProviderInfo destPi = dest.get(i).providerInfo;
6161 if (destPi.name == filterPi.name
6162 && destPi.packageName == filterPi.packageName) {
6163 return false;
6164 }
6165 }
6166 return true;
6167 }
6168
6169 @Override
6170 protected PackageParser.ProviderIntentInfo[] newArray(int size) {
6171 return new PackageParser.ProviderIntentInfo[size];
6172 }
6173
6174 @Override
6175 protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
6176 if (!sUserManager.exists(userId))
6177 return true;
6178 PackageParser.Package p = filter.provider.owner;
6179 if (p != null) {
6180 PackageSetting ps = (PackageSetting) p.mExtras;
6181 if (ps != null) {
6182 // System apps are never considered stopped for purposes of
6183 // filtering, because there may be no way for the user to
6184 // actually re-launch them.
6185 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
6186 && ps.getStopped(userId);
6187 }
6188 }
6189 return false;
6190 }
6191
6192 @Override
6193 protected boolean isPackageForFilter(String packageName,
6194 PackageParser.ProviderIntentInfo info) {
6195 return packageName.equals(info.provider.owner.packageName);
6196 }
6197
6198 @Override
6199 protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
6200 int match, int userId) {
6201 if (!sUserManager.exists(userId))
6202 return null;
6203 final PackageParser.ProviderIntentInfo info = filter;
6204 if (!mSettings.isEnabledLPr(info.provider.info, mFlags, userId)) {
6205 return null;
6206 }
6207 final PackageParser.Provider provider = info.provider;
6208 if (mSafeMode && (provider.info.applicationInfo.flags
6209 & ApplicationInfo.FLAG_SYSTEM) == 0) {
6210 return null;
6211 }
6212 PackageSetting ps = (PackageSetting) provider.owner.mExtras;
6213 if (ps == null) {
6214 return null;
6215 }
6216 ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
6217 ps.readUserState(userId), userId);
6218 if (pi == null) {
6219 return null;
6220 }
6221 final ResolveInfo res = new ResolveInfo();
6222 res.providerInfo = pi;
6223 if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
6224 res.filter = filter;
6225 }
6226 res.priority = info.getPriority();
6227 res.preferredOrder = provider.owner.mPreferredOrder;
6228 res.match = match;
6229 res.isDefault = info.hasDefault;
6230 res.labelRes = info.labelRes;
6231 res.nonLocalizedLabel = info.nonLocalizedLabel;
6232 res.icon = info.icon;
6233 res.system = isSystemApp(res.providerInfo.applicationInfo);
6234 return res;
6235 }
6236
6237 @Override
6238 protected void sortResults(List<ResolveInfo> results) {
6239 Collections.sort(results, mResolvePrioritySorter);
6240 }
6241
6242 @Override
6243 protected void dumpFilter(PrintWriter out, String prefix,
6244 PackageParser.ProviderIntentInfo filter) {
6245 out.print(prefix);
6246 out.print(
6247 Integer.toHexString(System.identityHashCode(filter.provider)));
6248 out.print(' ');
6249 filter.provider.printComponentShortName(out);
6250 out.print(" filter ");
6251 out.println(Integer.toHexString(System.identityHashCode(filter)));
6252 }
6253
6254 private final HashMap<ComponentName, PackageParser.Provider> mProviders
6255 = new HashMap<ComponentName, PackageParser.Provider>();
6256 private int mFlags;
6257 };
6258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
6260 new Comparator<ResolveInfo>() {
6261 public int compare(ResolveInfo r1, ResolveInfo r2) {
6262 int v1 = r1.priority;
6263 int v2 = r2.priority;
6264 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
6265 if (v1 != v2) {
6266 return (v1 > v2) ? -1 : 1;
6267 }
6268 v1 = r1.preferredOrder;
6269 v2 = r2.preferredOrder;
6270 if (v1 != v2) {
6271 return (v1 > v2) ? -1 : 1;
6272 }
6273 if (r1.isDefault != r2.isDefault) {
6274 return r1.isDefault ? -1 : 1;
6275 }
6276 v1 = r1.match;
6277 v2 = r2.match;
6278 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
Dianne Hackbornd99b2932011-08-18 14:39:58 -07006279 if (v1 != v2) {
6280 return (v1 > v2) ? -1 : 1;
6281 }
6282 if (r1.system != r2.system) {
6283 return r1.system ? -1 : 1;
6284 }
6285 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006286 }
6287 };
6288
6289 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
6290 new Comparator<ProviderInfo>() {
6291 public int compare(ProviderInfo p1, ProviderInfo p2) {
6292 final int v1 = p1.initOrder;
6293 final int v2 = p2.initOrder;
6294 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
6295 }
6296 };
6297
Kenny Root447106f2011-03-23 11:00:15 -07006298 static final void sendPackageBroadcast(String action, String pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006299 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
6300 int[] userIds) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 IActivityManager am = ActivityManagerNative.getDefault();
6302 if (am != null) {
6303 try {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006304 if (userIds == null) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07006305 userIds = am.getRunningUserIds();
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006306 }
Amith Yamasani13593602012-03-22 16:16:17 -07006307 for (int id : userIds) {
6308 final Intent intent = new Intent(action,
6309 pkg != null ? Uri.fromParts("package", pkg, null) : null);
6310 if (extras != null) {
6311 intent.putExtras(extras);
6312 }
6313 if (targetPkg != null) {
6314 intent.setPackage(targetPkg);
6315 }
6316 // Modify the UID when posting to other users
6317 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006318 if (uid > 0 && UserHandle.getUserId(uid) != id) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07006319 uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
Amith Yamasani13593602012-03-22 16:16:17 -07006320 intent.putExtra(Intent.EXTRA_UID, uid);
6321 }
Dianne Hackbornc72fc672012-09-20 13:12:03 -07006322 intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
Amith Yamasani13593602012-03-22 16:16:17 -07006323 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006324 if (DEBUG_BROADCASTS) {
6325 RuntimeException here = new RuntimeException("here");
6326 here.fillInStackTrace();
6327 Slog.d(TAG, "Sending to user " + id + ": "
6328 + intent.toShortString(false, true, false, false)
6329 + " " + intent.getExtras(), here);
6330 }
Amith Yamasani13593602012-03-22 16:16:17 -07006331 am.broadcastIntent(null, intent, null, finishedReceiver,
Dianne Hackbornf51f6122013-02-04 18:23:34 -08006332 0, null, null, null, android.app.AppOpsManager.OP_NONE,
6333 finishedReceiver != null, false, id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 } catch (RemoteException ex) {
6336 }
6337 }
6338 }
Kenny Root300c13a2011-01-18 13:04:40 -08006339
6340 /**
6341 * Check if the external storage media is available. This is true if there
6342 * is a mounted external storage medium or if the external storage is
6343 * emulated.
6344 */
6345 private boolean isExternalMediaAvailable() {
6346 return mMediaMounted || Environment.isExternalStorageEmulated();
6347 }
6348
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006349 public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07006350 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006351 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08006352 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006353 // If the external storage is no longer mounted at this point,
6354 // the caller may not have been able to delete all of this
6355 // packages files and can not delete any more. Bail.
6356 return null;
6357 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07006358 final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
6359 if (lastPackage != null) {
6360 pkgs.remove(lastPackage);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006361 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07006362 if (pkgs.size() > 0) {
6363 return pkgs.get(0);
6364 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006365 }
6366 return null;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006369 void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
6370 if (false) {
6371 RuntimeException here = new RuntimeException("here");
6372 here.fillInStackTrace();
6373 Slog.d(TAG, "Schedule cleaning " + packageName + " user=" + userId
6374 + " andCode=" + andCode, here);
6375 }
6376 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE,
6377 userId, andCode ? 1 : 0, packageName));
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006378 }
6379
Jeff Sharkey752cd922012-09-23 16:25:12 -07006380 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07006381 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006382 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08006383 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006384 return;
6385 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07006386 if (mSettings.mPackagesToBeCleaned.isEmpty()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006387 return;
6388 }
6389 }
6390 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
6391 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
6392 IActivityManager am = ActivityManagerNative.getDefault();
6393 if (am != null) {
6394 try {
Jeff Sharkey752cd922012-09-23 16:25:12 -07006395 am.startService(null, intent, null, UserHandle.USER_OWNER);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006396 } catch (RemoteException e) {
6397 }
6398 }
6399 }
6400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 private final class AppDirObserver extends FileObserver {
Christopher Tate409bb362013-07-12 12:29:41 -07006402 public AppDirObserver(String path, int mask, boolean isrom, boolean isPrivileged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 super(path, mask);
6404 mRootDir = path;
6405 mIsRom = isrom;
Christopher Tate409bb362013-07-12 12:29:41 -07006406 mIsPrivileged = isPrivileged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 }
6408
6409 public void onEvent(int event, String path) {
6410 String removedPackage = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006411 int removedAppId = -1;
Dianne Hackborn786b4402012-08-27 15:14:02 -07006412 int[] removedUsers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 String addedPackage = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006414 int addedAppId = -1;
Dianne Hackborn786b4402012-08-27 15:14:02 -07006415 int[] addedUsers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416
Kenny Root447106f2011-03-23 11:00:15 -07006417 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006418 synchronized (mInstallLock) {
6419 String fullPathStr = null;
6420 File fullPath = null;
6421 if (path != null) {
6422 fullPath = new File(mRootDir, path);
6423 fullPathStr = fullPath.getPath();
6424 }
6425
Kenny Root9718cf52011-02-23 16:45:26 -08006426 if (DEBUG_APP_DIR_OBSERVER)
6427 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006428
6429 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08006430 if (DEBUG_APP_DIR_OBSERVER)
6431 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006432 return;
6433 }
6434
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006435 // Ignore packages that are being installed or
6436 // have just been installed.
6437 if (ignoreCodePath(fullPathStr)) {
6438 return;
6439 }
6440 PackageParser.Package p = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006441 PackageSetting ps = null;
Kenny Root447106f2011-03-23 11:00:15 -07006442 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006443 synchronized (mPackages) {
6444 p = mAppDirs.get(fullPathStr);
Dianne Hackborn786b4402012-08-27 15:14:02 -07006445 if (p != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006446 ps = mSettings.mPackages.get(p.applicationInfo.packageName);
Dianne Hackborn786b4402012-08-27 15:14:02 -07006447 if (ps != null) {
6448 removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
6449 } else {
6450 removedUsers = sUserManager.getUserIds();
6451 }
6452 }
6453 addedUsers = sUserManager.getUserIds();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 if ((event&REMOVE_EVENTS) != 0) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006456 if (ps != null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07006457 if (DEBUG_REMOVE) Slog.d(TAG, "Package disappeared: " + ps);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006458 removePackageLI(ps, true);
6459 removedPackage = ps.name;
6460 removedAppId = ps.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006461 }
6462 }
6463
6464 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 if (p == null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07006466 if (DEBUG_INSTALL) Slog.d(TAG, "New file appeared: " + fullPath);
Christopher Tate409bb362013-07-12 12:29:41 -07006467 int flags = PackageParser.PARSE_CHATTY | PackageParser.PARSE_MUST_BE_APK;
6468 if (mIsRom) {
6469 flags |= PackageParser.PARSE_IS_SYSTEM
6470 | PackageParser.PARSE_IS_SYSTEM_DIR;
6471 if (mIsPrivileged) {
6472 flags |= PackageParser.PARSE_IS_PRIVILEGED;
6473 }
6474 }
6475 p = scanPackageLI(fullPath, flags,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006476 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
Dianne Hackborn786b4402012-08-27 15:14:02 -07006477 System.currentTimeMillis(), UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006478 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07006479 /*
6480 * TODO this seems dangerous as the package may have
6481 * changed since we last acquired the mPackages
6482 * lock.
6483 */
6484 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006486 updatePermissionsLPw(p.packageName, p,
Dianne Hackborne639da72012-02-21 15:11:13 -08006487 p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 }
6489 addedPackage = p.applicationInfo.packageName;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006490 addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 }
6492 }
6493 }
6494
Kenny Root447106f2011-03-23 11:00:15 -07006495 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006497 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 }
6499 }
6500
6501 if (removedPackage != null) {
6502 Bundle extras = new Bundle(1);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006503 extras.putInt(Intent.EXTRA_UID, removedAppId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006505 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborn786b4402012-08-27 15:14:02 -07006506 extras, null, null, removedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 }
6508 if (addedPackage != null) {
6509 Bundle extras = new Bundle(1);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006510 extras.putInt(Intent.EXTRA_UID, addedAppId);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006511 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Dianne Hackborn786b4402012-08-27 15:14:02 -07006512 extras, null, null, addedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006513 }
6514 }
6515
6516 private final String mRootDir;
6517 private final boolean mIsRom;
Christopher Tate409bb362013-07-12 12:29:41 -07006518 private final boolean mIsPrivileged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 /* Called when a downloaded package installation has been confirmed by the user */
6522 public void installPackage(
6523 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02006524 installPackage(packageURI, observer, flags, null);
6525 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006526
Jacek Surazski65e13172009-04-28 15:26:38 +02006527 /* Called when a downloaded package installation has been confirmed by the user */
6528 public void installPackage(
6529 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
6530 final String installerPackageName) {
Kenny Root5ab21572011-07-27 11:11:19 -07006531 installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
Rich Canningse1d7c712012-08-08 12:46:06 -07006532 null, null);
Kenny Root5ab21572011-07-27 11:11:19 -07006533 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006534
Kenny Root5ab21572011-07-27 11:11:19 -07006535 @Override
6536 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
6537 int flags, String installerPackageName, Uri verificationURI,
Rich Canningse1d7c712012-08-08 12:46:06 -07006538 ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
rich cannings706e8ba2012-08-20 13:20:14 -07006539 VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
Ben Gruver37d83a32012-09-27 13:02:06 -07006540 VerificationParams.NO_UID, manifestDigest);
rich cannings706e8ba2012-08-20 13:20:14 -07006541 installPackageWithVerificationAndEncryption(packageURI, observer, flags,
6542 installerPackageName, verificationParams, encryptionParams);
6543 }
6544
6545 public void installPackageWithVerificationAndEncryption(Uri packageURI,
6546 IPackageInstallObserver observer, int flags, String installerPackageName,
6547 VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
6548 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
6549 null);
Kenny Root5ab21572011-07-27 11:11:19 -07006550
6551 final int uid = Binder.getCallingUid();
Amith Yamasani71e6c692013-03-24 17:39:28 -07006552 if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006553 try {
6554 observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
6555 } catch (RemoteException re) {
6556 }
6557 return;
6558 }
6559
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006560 UserHandle user;
6561 if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
6562 user = UserHandle.ALL;
6563 } else {
Dianne Hackborn786b4402012-08-27 15:14:02 -07006564 user = new UserHandle(UserHandle.getUserId(uid));
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006565 }
Kenny Root5ab21572011-07-27 11:11:19 -07006566
6567 final int filteredFlags;
6568
6569 if (uid == Process.SHELL_UID || uid == 0) {
6570 if (DEBUG_INSTALL) {
6571 Slog.v(TAG, "Install from ADB");
6572 }
6573 filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
6574 } else {
6575 filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
6576 }
6577
rich cannings13d428e2012-09-13 13:43:07 -07006578 verificationParams.setInstallerUid(uid);
6579
Kenny Root5ab21572011-07-27 11:11:19 -07006580 final Message msg = mHandler.obtainMessage(INIT_COPY);
6581 msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006582 verificationParams, encryptionParams, user);
Kenny Root5ab21572011-07-27 11:11:19 -07006583 mHandler.sendMessage(msg);
6584 }
6585
Amith Yamasani655d0e22013-06-12 14:19:10 -07006586 private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting, int userId) {
6587 Bundle extras = new Bundle(1);
6588 extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
6589
6590 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
6591 packageName, extras, null, null, new int[] {userId});
6592 try {
6593 IActivityManager am = ActivityManagerNative.getDefault();
6594 final boolean isSystem =
6595 isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
6596 if (isSystem && am.isUserRunning(userId, false)) {
6597 // The just-installed/enabled app is bundled on the system, so presumed
6598 // to be able to run automatically without needing an explicit launch.
6599 // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
6600 Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
6601 .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
6602 .setPackage(packageName);
6603 am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
6604 android.app.AppOpsManager.OP_NONE, false, false, userId);
6605 }
6606 } catch (RemoteException e) {
6607 // shouldn't happen
6608 Slog.w(TAG, "Unable to bootstrap installed package", e);
6609 }
6610 }
6611
6612 @Override
6613 public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
6614 int userId) {
6615 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
6616 PackageSetting pkgSetting;
6617 final int uid = Binder.getCallingUid();
6618 if (UserHandle.getUserId(uid) != userId) {
Amith Yamasani1a7472e2013-07-02 11:17:30 -07006619 mContext.enforceCallingOrSelfPermission(
Amith Yamasani655d0e22013-06-12 14:19:10 -07006620 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
Amith Yamasani1a7472e2013-07-02 11:17:30 -07006621 "setApplicationBlockedSetting for user " + userId);
Amith Yamasani655d0e22013-06-12 14:19:10 -07006622 }
6623
6624 if (blocked && isPackageDeviceAdmin(packageName, userId)) {
6625 Slog.w(TAG, "Not blocking package " + packageName + ": has active device admin");
6626 return false;
6627 }
6628
6629 long callingId = Binder.clearCallingIdentity();
6630 try {
6631 boolean sendAdded = false;
6632 boolean sendRemoved = false;
6633 // writer
6634 synchronized (mPackages) {
6635 pkgSetting = mSettings.mPackages.get(packageName);
6636 if (pkgSetting == null) {
6637 return false;
6638 }
6639 if (pkgSetting.getBlocked(userId) != blocked) {
6640 pkgSetting.setBlocked(blocked, userId);
6641 mSettings.writePackageRestrictionsLPr(userId);
6642 if (blocked) {
6643 sendRemoved = true;
6644 } else {
6645 sendAdded = true;
6646 }
6647 }
6648 }
6649 if (sendAdded) {
6650 sendPackageAddedForUser(packageName, pkgSetting, userId);
6651 return true;
6652 }
6653 if (sendRemoved) {
Amith Yamasani1a7472e2013-07-02 11:17:30 -07006654 killApplication(packageName, UserHandle.getUid(userId, pkgSetting.appId),
6655 "blocking pkg");
Amith Yamasani655d0e22013-06-12 14:19:10 -07006656 sendPackageBlockedForUser(packageName, pkgSetting, userId);
6657 }
6658 } finally {
6659 Binder.restoreCallingIdentity(callingId);
6660 }
6661 return false;
6662 }
6663
6664 private void sendPackageBlockedForUser(String packageName, PackageSetting pkgSetting,
6665 int userId) {
6666 final PackageRemovedInfo info = new PackageRemovedInfo();
6667 info.removedPackage = packageName;
6668 info.removedUsers = new int[] {userId};
6669 info.uid = UserHandle.getUid(userId, pkgSetting.appId);
6670 info.sendBroadcast(false, false, false);
6671 }
6672
6673 /**
6674 * Returns true if application is not found or there was an error. Otherwise it returns
6675 * the blocked state of the package for the given user.
6676 */
6677 @Override
6678 public boolean getApplicationBlockedSettingAsUser(String packageName, int userId) {
6679 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
6680 PackageSetting pkgSetting;
6681 final int uid = Binder.getCallingUid();
6682 if (UserHandle.getUserId(uid) != userId) {
6683 mContext.enforceCallingPermission(
6684 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6685 "getApplicationBlocked for user " + userId);
6686 }
6687 long callingId = Binder.clearCallingIdentity();
6688 try {
6689 // writer
6690 synchronized (mPackages) {
6691 pkgSetting = mSettings.mPackages.get(packageName);
6692 if (pkgSetting == null) {
6693 return true;
6694 }
6695 return pkgSetting.getBlocked(userId);
6696 }
6697 } finally {
6698 Binder.restoreCallingIdentity(callingId);
6699 }
6700 }
6701
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006702 /**
6703 * @hide
6704 */
6705 @Override
Amith Yamasani67df64b2012-12-14 12:09:36 -08006706 public int installExistingPackageAsUser(String packageName, int userId) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006707 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
6708 null);
6709 PackageSetting pkgSetting;
6710 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08006711 if (UserHandle.getUserId(uid) != userId) {
6712 mContext.enforceCallingPermission(
6713 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6714 "installExistingPackage for user " + userId);
6715 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07006716 if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006717 return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
6718 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006719
6720 long callingId = Binder.clearCallingIdentity();
6721 try {
6722 boolean sendAdded = false;
6723 Bundle extras = new Bundle(1);
6724
6725 // writer
6726 synchronized (mPackages) {
6727 pkgSetting = mSettings.mPackages.get(packageName);
6728 if (pkgSetting == null) {
6729 return PackageManager.INSTALL_FAILED_INVALID_URI;
6730 }
6731 if (!pkgSetting.getInstalled(userId)) {
6732 pkgSetting.setInstalled(true, userId);
Amith Yamasani655d0e22013-06-12 14:19:10 -07006733 pkgSetting.setBlocked(false, userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006734 mSettings.writePackageRestrictionsLPr(userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006735 sendAdded = true;
6736 }
6737 }
6738
6739 if (sendAdded) {
Amith Yamasani655d0e22013-06-12 14:19:10 -07006740 sendPackageAddedForUser(packageName, pkgSetting, userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006741 }
6742 } finally {
6743 Binder.restoreCallingIdentity(callingId);
6744 }
6745
6746 return PackageManager.INSTALL_SUCCEEDED;
6747 }
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006748
Amith Yamasani71e6c692013-03-24 17:39:28 -07006749 private boolean isUserRestricted(int userId, String restrictionKey) {
Amith Yamasani67df64b2012-12-14 12:09:36 -08006750 Bundle restrictions = sUserManager.getUserRestrictions(userId);
Amith Yamasani71e6c692013-03-24 17:39:28 -07006751 if (restrictions.getBoolean(restrictionKey, false)) {
6752 Log.w(TAG, "User is restricted: " + restrictionKey);
6753 return true;
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006754 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07006755 return false;
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006756 }
6757
Kenny Root5ab21572011-07-27 11:11:19 -07006758 @Override
Kenny Root05ca4c92011-09-15 10:36:25 -07006759 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
rich cannings7e671512012-08-27 14:44:16 -07006760 mContext.enforceCallingOrSelfPermission(
6761 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6762 "Only package verification agents can verify applications");
6763
Kenny Root5ab21572011-07-27 11:11:19 -07006764 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
Kenny Root05ca4c92011-09-15 10:36:25 -07006765 final PackageVerificationResponse response = new PackageVerificationResponse(
6766 verificationCode, Binder.getCallingUid());
Kenny Root5ab21572011-07-27 11:11:19 -07006767 msg.arg1 = id;
Kenny Root05ca4c92011-09-15 10:36:25 -07006768 msg.obj = response;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006769 mHandler.sendMessage(msg);
6770 }
6771
rich canningsd9ef3e52012-08-22 14:28:05 -07006772 @Override
6773 public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
6774 long millisecondsToDelay) {
rich cannings7e671512012-08-27 14:44:16 -07006775 mContext.enforceCallingOrSelfPermission(
6776 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6777 "Only package verification agents can extend verification timeouts");
6778
rich canningsd9ef3e52012-08-22 14:28:05 -07006779 final PackageVerificationState state = mPendingVerification.get(id);
6780 final PackageVerificationResponse response = new PackageVerificationResponse(
6781 verificationCodeAtTimeout, Binder.getCallingUid());
6782
rich canningsd1b5cfc2012-08-29 14:49:51 -07006783 if (millisecondsToDelay > PackageManager.MAXIMUM_VERIFICATION_TIMEOUT) {
6784 millisecondsToDelay = PackageManager.MAXIMUM_VERIFICATION_TIMEOUT;
6785 }
6786 if (millisecondsToDelay < 0) {
6787 millisecondsToDelay = 0;
rich canningsd9ef3e52012-08-22 14:28:05 -07006788 }
6789 if ((verificationCodeAtTimeout != PackageManager.VERIFICATION_ALLOW)
rich canningsd1b5cfc2012-08-29 14:49:51 -07006790 && (verificationCodeAtTimeout != PackageManager.VERIFICATION_REJECT)) {
6791 verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
rich canningsd9ef3e52012-08-22 14:28:05 -07006792 }
6793
6794 if ((state != null) && !state.timeoutExtended()) {
6795 state.extendTimeout();
6796
6797 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
6798 msg.arg1 = id;
6799 msg.obj = response;
6800 mHandler.sendMessageDelayed(msg, millisecondsToDelay);
6801 }
6802 }
6803
rich canningsd1b5cfc2012-08-29 14:49:51 -07006804 private void broadcastPackageVerified(int verificationId, Uri packageUri,
rich canningsd55deb02012-10-02 14:53:08 -07006805 int verificationCode, UserHandle user) {
rich canningsd1b5cfc2012-08-29 14:49:51 -07006806 final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
6807 intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
6808 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
6809 intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
6810 intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode);
6811
rich canningsd55deb02012-10-02 14:53:08 -07006812 mContext.sendBroadcastAsUser(intent, user,
6813 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
rich canningsd1b5cfc2012-08-29 14:49:51 -07006814 }
6815
Kenny Root05ca4c92011-09-15 10:36:25 -07006816 private ComponentName matchComponentForVerifier(String packageName,
6817 List<ResolveInfo> receivers) {
6818 ActivityInfo targetReceiver = null;
6819
6820 final int NR = receivers.size();
6821 for (int i = 0; i < NR; i++) {
6822 final ResolveInfo info = receivers.get(i);
6823 if (info.activityInfo == null) {
6824 continue;
6825 }
6826
6827 if (packageName.equals(info.activityInfo.packageName)) {
6828 targetReceiver = info.activityInfo;
6829 break;
6830 }
6831 }
6832
6833 if (targetReceiver == null) {
6834 return null;
6835 }
6836
6837 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
6838 }
6839
6840 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
6841 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
6842 if (pkgInfo.verifiers.length == 0) {
6843 return null;
6844 }
6845
6846 final int N = pkgInfo.verifiers.length;
6847 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
6848 for (int i = 0; i < N; i++) {
6849 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
6850
6851 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
6852 receivers);
6853 if (comp == null) {
6854 continue;
6855 }
6856
6857 final int verifierUid = getUidForVerifier(verifierInfo);
6858 if (verifierUid == -1) {
6859 continue;
6860 }
6861
6862 if (DEBUG_VERIFY) {
6863 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
6864 + " with the correct signature");
6865 }
6866 sufficientVerifiers.add(comp);
6867 verificationState.addSufficientVerifier(verifierUid);
6868 }
6869
6870 return sufficientVerifiers;
6871 }
6872
6873 private int getUidForVerifier(VerifierInfo verifierInfo) {
6874 synchronized (mPackages) {
6875 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
6876 if (pkg == null) {
6877 return -1;
6878 } else if (pkg.mSignatures.length != 1) {
6879 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
6880 + " has more than one signature; ignoring");
6881 return -1;
6882 }
6883
6884 /*
6885 * If the public key of the package's signature does not match
6886 * our expected public key, then this is a different package and
6887 * we should skip.
6888 */
6889
6890 final byte[] expectedPublicKey;
6891 try {
6892 final Signature verifierSig = pkg.mSignatures[0];
6893 final PublicKey publicKey = verifierSig.getPublicKey();
6894 expectedPublicKey = publicKey.getEncoded();
6895 } catch (CertificateException e) {
6896 return -1;
6897 }
6898
6899 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
6900
6901 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
6902 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
6903 + " does not have the expected public key; ignoring");
6904 return -1;
6905 }
6906
6907 return pkg.applicationInfo.uid;
6908 }
6909 }
6910
Christopher Tate1bb69062010-02-19 17:02:12 -08006911 public void finishPackageInstall(int token) {
Kenny Root461ff1f2011-08-09 09:43:03 -07006912 enforceSystemOrRoot("Only the system is allowed to finish installs");
6913
6914 if (DEBUG_INSTALL) {
6915 Slog.v(TAG, "BM finishing package install for " + token);
6916 }
6917
6918 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
Christopher Tate1bb69062010-02-19 17:02:12 -08006919 mHandler.sendMessage(msg);
6920 }
6921
Kenny Root5ab21572011-07-27 11:11:19 -07006922 /**
6923 * Get the verification agent timeout.
6924 *
6925 * @return verification timeout in milliseconds
6926 */
6927 private long getVerificationTimeout() {
rich cannings4d8fc792012-09-07 14:43:43 -07006928 return android.provider.Settings.Global.getLong(mContext.getContentResolver(),
6929 android.provider.Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
Kenny Root5ab21572011-07-27 11:11:19 -07006930 DEFAULT_VERIFICATION_TIMEOUT);
6931 }
6932
6933 /**
rich canningsa6cfe522012-05-21 15:50:56 -07006934 * Get the default verification agent response code.
6935 *
6936 * @return default verification response code
6937 */
6938 private int getDefaultVerificationResponse() {
rich cannings4d8fc792012-09-07 14:43:43 -07006939 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
6940 android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
rich canningsa6cfe522012-05-21 15:50:56 -07006941 DEFAULT_VERIFICATION_RESPONSE);
6942 }
6943
6944 /**
Kenny Root5ab21572011-07-27 11:11:19 -07006945 * Check whether or not package verification has been enabled.
6946 *
6947 * @return true if verification should be performed
6948 */
rich cannings4e5753f2012-09-19 16:03:56 -07006949 private boolean isVerificationEnabled(int flags) {
rich canningse4bf0ea2012-09-14 13:18:55 -07006950 if (!DEFAULT_VERIFY_ENABLE) {
6951 return false;
6952 }
6953
rich cannings4e5753f2012-09-19 16:03:56 -07006954 // Check if installing from ADB
6955 if ((flags & PackageManager.INSTALL_FROM_ADB) != 0) {
rich canningsa2064df2012-09-30 14:52:41 -07006956 // Do not run verification in a test harness environment
6957 if (ActivityManager.isRunningInTestHarness()) {
6958 return false;
6959 }
rich cannings4e5753f2012-09-19 16:03:56 -07006960 // Check if the developer does not want package verification for ADB installs
6961 if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
6962 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
6963 return false;
6964 }
6965 }
6966
rich cannings4d8fc792012-09-07 14:43:43 -07006967 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
rich canningse4bf0ea2012-09-14 13:18:55 -07006968 android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
Kenny Root5ab21572011-07-27 11:11:19 -07006969 }
6970
Matt Finifterf8a98ed2012-05-14 15:43:34 -07006971 /**
6972 * Get the "allow unknown sources" setting.
6973 *
6974 * @return the current "allow unknown sources" setting
6975 */
6976 private int getUnknownSourcesSettings() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -07006977 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
6978 android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
Matt Finifterf8a98ed2012-05-14 15:43:34 -07006979 -1);
6980 }
6981
Kenny Rootf03b45f2011-02-23 17:25:45 -08006982 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08006983 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07006984 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08006985 synchronized (mPackages) {
6986 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
6987 if (targetPackageSetting == null) {
6988 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
6989 }
6990
6991 PackageSetting installerPackageSetting;
6992 if (installerPackageName != null) {
6993 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
6994 if (installerPackageSetting == null) {
6995 throw new IllegalArgumentException("Unknown installer package: "
6996 + installerPackageName);
6997 }
6998 } else {
6999 installerPackageSetting = null;
7000 }
7001
7002 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07007003 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08007004 if (obj != null) {
7005 if (obj instanceof SharedUserSetting) {
7006 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
7007 } else if (obj instanceof PackageSetting) {
7008 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
7009 } else {
7010 throw new SecurityException("Bad object " + obj + " for uid " + uid);
7011 }
7012 } else {
7013 throw new SecurityException("Unknown calling uid " + uid);
7014 }
7015
7016 // Verify: can't set installerPackageName to a package that is
7017 // not signed with the same cert as the caller.
7018 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007019 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08007020 installerPackageSetting.signatures.mSignatures)
7021 != PackageManager.SIGNATURE_MATCH) {
7022 throw new SecurityException(
7023 "Caller does not have same cert as new installer package "
7024 + installerPackageName);
7025 }
7026 }
7027
7028 // Verify: if target already has an installer package, it must
7029 // be signed with the same cert as the caller.
7030 if (targetPackageSetting.installerPackageName != null) {
7031 PackageSetting setting = mSettings.mPackages.get(
7032 targetPackageSetting.installerPackageName);
7033 // If the currently set package isn't valid, then it's always
7034 // okay to change it.
7035 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007036 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08007037 setting.signatures.mSignatures)
7038 != PackageManager.SIGNATURE_MATCH) {
7039 throw new SecurityException(
7040 "Caller does not have same cert as old installer package "
7041 + targetPackageSetting.installerPackageName);
7042 }
7043 }
7044 }
7045
7046 // Okay!
7047 targetPackageSetting.installerPackageName = installerPackageName;
7048 scheduleWriteSettingsLocked();
7049 }
7050 }
7051
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007052 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 // Queue up an async operation since the package installation may take a little while.
7054 mHandler.post(new Runnable() {
7055 public void run() {
7056 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007057 // Result object to be returned
7058 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007059 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007060 res.uid = -1;
7061 res.pkg = null;
7062 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007063 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007064 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007065 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007066 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007067 }
Kenny Root6dceb882012-04-12 14:23:49 -07007068 args.doPostInstall(res.returnCode, res.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007069 }
Christopher Tate1bb69062010-02-19 17:02:12 -08007070
7071 // A restore should be performed at this point if (a) the install
7072 // succeeded, (b) the operation is not an update, and (c) the new
7073 // package has a backupAgent defined.
7074 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08007075 boolean doRestore = (!update
7076 && res.pkg != null
7077 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08007078
7079 // Set up the post-install work request bookkeeping. This will be used
7080 // and cleaned up by the post-install event handling regardless of whether
7081 // there's a restore pass performed. Token values are >= 1.
7082 int token;
7083 if (mNextInstallToken < 0) mNextInstallToken = 1;
7084 token = mNextInstallToken++;
7085
7086 PostInstallData data = new PostInstallData(args, res);
7087 mRunningInstalls.put(token, data);
7088 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
7089
7090 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
7091 // Pass responsibility to the Backup Manager. It will perform a
7092 // restore if appropriate, then pass responsibility back to the
7093 // Package Manager to run the post-install observer callbacks
7094 // and broadcasts.
7095 IBackupManager bm = IBackupManager.Stub.asInterface(
7096 ServiceManager.getService(Context.BACKUP_SERVICE));
7097 if (bm != null) {
7098 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
7099 + " to BM for possible restore");
7100 try {
7101 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
7102 } catch (RemoteException e) {
7103 // can't happen; the backup manager is local
7104 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007105 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08007106 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007107 }
Christopher Tate1bb69062010-02-19 17:02:12 -08007108 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007109 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08007110 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007112 }
Christopher Tate1bb69062010-02-19 17:02:12 -08007113
7114 if (!doRestore) {
7115 // No restore possible, or the Backup Manager was mysteriously not
7116 // available -- just fire the post-install work request directly.
7117 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
7118 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
7119 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 }
7122 });
7123 }
7124
Kenny Root5ab21572011-07-27 11:11:19 -07007125 private abstract class HandlerParams {
7126 private static final int MAX_RETRIES = 4;
7127
7128 /**
7129 * Number of times startCopy() has been attempted and had a non-fatal
7130 * error.
7131 */
7132 private int mRetries = 0;
7133
Amith Yamasani6ec10122012-08-23 13:49:25 -07007134 /** User handle for the user requesting the information or installation. */
7135 private final UserHandle mUser;
7136
7137 HandlerParams(UserHandle user) {
7138 mUser = user;
7139 }
7140
7141 UserHandle getUser() {
7142 return mUser;
7143 }
7144
Dianne Hackborn7d608422011-08-07 16:24:18 -07007145 final boolean startCopy() {
7146 boolean res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007147 try {
Dianne Hackbornc895be72013-03-11 17:48:43 -07007148 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
Kenny Root5ab21572011-07-27 11:11:19 -07007149
7150 if (++mRetries > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007151 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007152 mHandler.sendEmptyMessage(MCS_GIVE_UP);
7153 handleServiceError();
Dianne Hackborn7d608422011-08-07 16:24:18 -07007154 return false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007155 } else {
7156 handleStartCopy();
Dianne Hackborn7d608422011-08-07 16:24:18 -07007157 res = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007158 }
7159 } catch (RemoteException e) {
Kenny Root5ab21572011-07-27 11:11:19 -07007160 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007161 mHandler.sendEmptyMessage(MCS_RECONNECT);
Dianne Hackborn7d608422011-08-07 16:24:18 -07007162 res = false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007163 }
7164 handleReturnCode();
Dianne Hackborn7d608422011-08-07 16:24:18 -07007165 return res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007166 }
7167
7168 final void serviceError() {
Kenny Root5ab21572011-07-27 11:11:19 -07007169 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007170 handleServiceError();
7171 handleReturnCode();
7172 }
Kenny Root5ab21572011-07-27 11:11:19 -07007173
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007174 abstract void handleStartCopy() throws RemoteException;
7175 abstract void handleServiceError();
7176 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007177 }
7178
Kenny Root366949c2011-01-14 17:18:14 -08007179 class MeasureParams extends HandlerParams {
7180 private final PackageStats mStats;
7181 private boolean mSuccess;
7182
7183 private final IPackageStatsObserver mObserver;
7184
Kenny Roota69b7eb2012-05-14 14:47:06 -07007185 public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
Amith Yamasani6ec10122012-08-23 13:49:25 -07007186 super(new UserHandle(stats.userHandle));
Kenny Root366949c2011-01-14 17:18:14 -08007187 mObserver = observer;
7188 mStats = stats;
Kenny Root366949c2011-01-14 17:18:14 -08007189 }
7190
7191 @Override
Dianne Hackbornc895be72013-03-11 17:48:43 -07007192 public String toString() {
7193 return "MeasureParams{"
7194 + Integer.toHexString(System.identityHashCode(this))
7195 + " " + mStats.packageName + "}";
7196 }
7197
7198 @Override
Kenny Root366949c2011-01-14 17:18:14 -08007199 void handleStartCopy() throws RemoteException {
Kenny Roota69b7eb2012-05-14 14:47:06 -07007200 synchronized (mInstallLock) {
Dianne Hackborn0c380492012-08-20 17:23:30 -07007201 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
Kenny Roota69b7eb2012-05-14 14:47:06 -07007202 }
Kenny Root366949c2011-01-14 17:18:14 -08007203
Kenny Roota69b7eb2012-05-14 14:47:06 -07007204 final boolean mounted;
Kenny Root366949c2011-01-14 17:18:14 -08007205 if (Environment.isExternalStorageEmulated()) {
7206 mounted = true;
7207 } else {
7208 final String status = Environment.getExternalStorageState();
Jeff Sharkeyb049e212012-09-07 23:16:01 -07007209 mounted = (Environment.MEDIA_MOUNTED.equals(status)
7210 || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
Kenny Root366949c2011-01-14 17:18:14 -08007211 }
7212
7213 if (mounted) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07007214 final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
7215
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007216 mStats.externalCacheSize = calculateDirectorySize(mContainerService,
7217 userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
Kenny Root366949c2011-01-14 17:18:14 -08007218
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007219 mStats.externalDataSize = calculateDirectorySize(mContainerService,
7220 userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
Kenny Root366949c2011-01-14 17:18:14 -08007221
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007222 // Always subtract cache size, since it's a subdirectory
7223 mStats.externalDataSize -= mStats.externalCacheSize;
Kenny Root366949c2011-01-14 17:18:14 -08007224
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007225 mStats.externalMediaSize = calculateDirectorySize(mContainerService,
7226 userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
Kenny Rootbcd6c962011-01-17 11:21:49 -08007227
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007228 mStats.externalObbSize = calculateDirectorySize(mContainerService,
7229 userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
Kenny Root366949c2011-01-14 17:18:14 -08007230 }
7231 }
7232
7233 @Override
7234 void handleReturnCode() {
7235 if (mObserver != null) {
7236 try {
7237 mObserver.onGetStatsCompleted(mStats, mSuccess);
7238 } catch (RemoteException e) {
7239 Slog.i(TAG, "Observer no longer exists.");
7240 }
7241 }
7242 }
7243
7244 @Override
7245 void handleServiceError() {
7246 Slog.e(TAG, "Could not measure application " + mStats.packageName
7247 + " external storage");
7248 }
7249 }
7250
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007251 private static long calculateDirectorySize(IMediaContainerService mcs, File[] paths)
7252 throws RemoteException {
7253 long result = 0;
7254 for (File path : paths) {
7255 result += mcs.calculateDirectorySize(path.getAbsolutePath());
7256 }
7257 return result;
7258 }
7259
7260 private static void clearDirectory(IMediaContainerService mcs, File[] paths) {
7261 for (File path : paths) {
7262 try {
7263 mcs.clearDirectory(path.getAbsolutePath());
7264 } catch (RemoteException e) {
7265 }
7266 }
7267 }
7268
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007269 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007270 final IPackageInstallObserver observer;
7271 int flags;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007272
7273 private final Uri mPackageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007274 final String installerPackageName;
rich cannings706e8ba2012-08-20 13:20:14 -07007275 final VerificationParams verificationParams;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007276 private InstallArgs mArgs;
7277 private int mRet;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007278 private File mTempPackage;
7279 final ContainerEncryptionParams encryptionParams;
Kenny Root5ab21572011-07-27 11:11:19 -07007280
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007281 InstallParams(Uri packageURI,
7282 IPackageInstallObserver observer, int flags,
rich cannings706e8ba2012-08-20 13:20:14 -07007283 String installerPackageName, VerificationParams verificationParams,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007284 ContainerEncryptionParams encryptionParams, UserHandle user) {
Amith Yamasani6ec10122012-08-23 13:49:25 -07007285 super(user);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007286 this.mPackageURI = packageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007287 this.flags = flags;
7288 this.observer = observer;
7289 this.installerPackageName = installerPackageName;
rich cannings706e8ba2012-08-20 13:20:14 -07007290 this.verificationParams = verificationParams;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007291 this.encryptionParams = encryptionParams;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007292 }
7293
Dianne Hackbornc895be72013-03-11 17:48:43 -07007294 @Override
7295 public String toString() {
7296 return "InstallParams{"
7297 + Integer.toHexString(System.identityHashCode(this))
7298 + " " + mPackageURI + "}";
7299 }
7300
rich cannings706e8ba2012-08-20 13:20:14 -07007301 public ManifestDigest getManifestDigest() {
7302 if (verificationParams == null) {
7303 return null;
7304 }
7305 return verificationParams.getManifestDigest();
7306 }
7307
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007308 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
7309 String packageName = pkgLite.packageName;
7310 int installLocation = pkgLite.installLocation;
7311 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07007312 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007313 synchronized (mPackages) {
7314 PackageParser.Package pkg = mPackages.get(packageName);
7315 if (pkg != null) {
7316 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007317 // Check for downgrading.
7318 if ((flags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
7319 if (pkgLite.versionCode < pkg.mVersionCode) {
7320 Slog.w(TAG, "Can't install update of " + packageName
7321 + " update version " + pkgLite.versionCode
7322 + " is older than installed version "
7323 + pkg.mVersionCode);
7324 return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
7325 }
7326 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007327 // Check for updated system application.
7328 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7329 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007330 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007331 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
7332 }
7333 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
7334 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007335 if (onSd) {
7336 // Install flag overrides everything.
7337 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
7338 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07007339 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007340 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
7341 // Application explicitly specified internal.
7342 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
7343 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
7344 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07007345 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007346 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07007347 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07007348 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
7349 }
7350 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007351 }
7352 }
7353 } else {
7354 // Invalid install. Return error code
7355 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
7356 }
7357 }
7358 }
7359 // All the special cases have been taken care of.
7360 // Return result based on recommended install location.
7361 if (onSd) {
7362 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
7363 }
7364 return pkgLite.recommendedInstallLocation;
7365 }
7366
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08007367 private long getMemoryLowThreshold() {
7368 final DeviceStorageMonitorInternal
7369 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
7370 if (dsm == null) {
7371 return 0L;
7372 }
7373 return dsm.getMemoryLowThreshold();
7374 }
7375
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007376 /*
7377 * Invoke remote method to get package information and install
7378 * location values. Override install location based on default
7379 * policy if needed and then create install arguments based
7380 * on the install location.
7381 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007382 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08007383 int ret = PackageManager.INSTALL_SUCCEEDED;
Kenny Root05ca4c92011-09-15 10:36:25 -07007384 final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
7385 final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
7386 PackageInfoLite pkgLite = null;
7387
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007388 if (onInt && onSd) {
7389 // Check if both bits are set.
7390 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
7391 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007392 } else {
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08007393 final long lowThreshold = getMemoryLowThreshold();
7394 if (lowThreshold == 0L) {
Kenny Root62e1b4e2011-03-14 17:13:39 -07007395 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
Kenny Root62e1b4e2011-03-14 17:13:39 -07007396 }
7397
Kenny Root11128572010-10-11 10:51:32 -07007398 try {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007399 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
Kenny Root11128572010-10-11 10:51:32 -07007400 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root11128572010-10-11 10:51:32 -07007401
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007402 final File packageFile;
7403 if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007404 mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
7405 if (mTempPackage != null) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -08007406 ParcelFileDescriptor out;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007407 try {
7408 out = ParcelFileDescriptor.open(mTempPackage,
7409 ParcelFileDescriptor.MODE_READ_WRITE);
7410 } catch (FileNotFoundException e) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -08007411 out = null;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007412 Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
7413 }
7414
7415 // Make a temporary file for decryption.
7416 ret = mContainerService
7417 .copyResource(mPackageURI, encryptionParams, out);
Dianne Hackborn40e9f292012-11-27 19:12:23 -08007418 IoUtils.closeQuietly(out);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007419
7420 packageFile = mTempPackage;
7421
7422 FileUtils.setPermissions(packageFile.getAbsolutePath(),
Kenny Root0b2fa8c2012-09-14 10:26:16 -07007423 FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP
7424 | FileUtils.S_IROTH,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007425 -1, -1);
7426 } else {
7427 packageFile = null;
7428 }
7429 } else {
7430 packageFile = new File(mPackageURI.getPath());
7431 }
7432
7433 if (packageFile != null) {
7434 // Remote call to find out default install location
Kenny Rootcea37432012-10-18 14:57:33 -07007435 final String packageFilePath = packageFile.getAbsolutePath();
7436 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
7437 lowThreshold);
7438
7439 /*
7440 * If we have too little free space, try to free cache
7441 * before giving up.
7442 */
7443 if (pkgLite.recommendedInstallLocation
7444 == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
7445 final long size = mContainerService.calculateInstalledSize(
7446 packageFilePath, isForwardLocked());
7447 if (mInstaller.freeCache(size + lowThreshold) >= 0) {
7448 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
7449 flags, lowThreshold);
7450 }
Kenny Root3f96d0e2012-12-11 12:48:08 -08007451 /*
7452 * The cache free must have deleted the file we
7453 * downloaded to install.
7454 *
7455 * TODO: fix the "freeCache" call to not delete
7456 * the file we care about.
7457 */
7458 if (pkgLite.recommendedInstallLocation
7459 == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
7460 pkgLite.recommendedInstallLocation
7461 = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
7462 }
Kenny Rootcea37432012-10-18 14:57:33 -07007463 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007464 }
7465 } finally {
7466 mContext.revokeUriPermission(mPackageURI,
7467 Intent.FLAG_GRANT_READ_URI_PERMISSION);
7468 }
7469 }
7470
7471 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007472 int loc = pkgLite.recommendedInstallLocation;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007473 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007474 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007475 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007476 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007477 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007478 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7479 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
7480 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007481 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
7482 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007483 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
Kenny Root1ebd74a2011-08-03 15:09:44 -07007484 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007485 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007486 // Override with defaults if needed.
7487 loc = installLocationPolicy(pkgLite, flags);
Kenny Roota3e90792012-10-18 10:58:36 -07007488 if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
7489 ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
7490 } else if (!onSd && !onInt) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007491 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007492 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
7493 // Set the flag to install on external media.
7494 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007495 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007496 } else {
7497 // Make sure the flag for installing on external
7498 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007499 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007500 flags &= ~PackageManager.INSTALL_EXTERNAL;
7501 }
7502 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007503 }
7504 }
Kenny Root5ab21572011-07-27 11:11:19 -07007505
7506 final InstallArgs args = createInstallArgs(this);
Kenny Root05ca4c92011-09-15 10:36:25 -07007507 mArgs = args;
7508
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007509 if (ret == PackageManager.INSTALL_SUCCEEDED) {
rich cannings36070b42012-10-09 11:50:15 -07007510 /*
7511 * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
7512 * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
7513 */
7514 int userIdentifier = getUser().getIdentifier();
7515 if (userIdentifier == UserHandle.USER_ALL
7516 && ((flags & PackageManager.INSTALL_FROM_ADB) != 0)) {
7517 userIdentifier = UserHandle.USER_OWNER;
7518 }
7519
Kenny Root5ab21572011-07-27 11:11:19 -07007520 /*
7521 * Determine if we have any installed package verifiers. If we
7522 * do, then we'll defer to them to verify the packages.
7523 */
Kenny Root05ca4c92011-09-15 10:36:25 -07007524 final int requiredUid = mRequiredVerifierPackage == null ? -1
rich cannings36070b42012-10-09 11:50:15 -07007525 : getPackageUid(mRequiredVerifierPackage, userIdentifier);
rich cannings4e5753f2012-09-19 16:03:56 -07007526 if (requiredUid != -1 && isVerificationEnabled(flags)) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007527 final Intent verification = new Intent(
7528 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
7529 verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
Kenny Root05ca4c92011-09-15 10:36:25 -07007530 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root5ab21572011-07-27 11:11:19 -07007531
Andy Stadler250ce282012-08-24 16:09:03 -07007532 final List<ResolveInfo> receivers = queryIntentReceivers(verification,
7533 PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
7534 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07007535
7536 if (DEBUG_VERIFY) {
Kenny Root5ab21572011-07-27 11:11:19 -07007537 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
Kenny Root05ca4c92011-09-15 10:36:25 -07007538 + verification.toString() + " with " + pkgLite.verifiers.length
7539 + " optional verifiers");
Kenny Root5ab21572011-07-27 11:11:19 -07007540 }
7541
7542 final int verificationId = mPendingVerificationToken++;
7543
7544 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
7545
7546 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
7547 installerPackageName);
7548
7549 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
7550
rich cannings13d428e2012-09-13 13:43:07 -07007551 verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
7552 pkgLite.packageName);
7553
7554 verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
7555 pkgLite.versionCode);
7556
rich cannings706e8ba2012-08-20 13:20:14 -07007557 if (verificationParams != null) {
7558 if (verificationParams.getVerificationURI() != null) {
7559 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
7560 verificationParams.getVerificationURI());
7561 }
7562 if (verificationParams.getOriginatingURI() != null) {
7563 verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
7564 verificationParams.getOriginatingURI());
7565 }
7566 if (verificationParams.getReferrer() != null) {
7567 verification.putExtra(Intent.EXTRA_REFERRER,
7568 verificationParams.getReferrer());
7569 }
Ben Gruver37d83a32012-09-27 13:02:06 -07007570 if (verificationParams.getOriginatingUid() >= 0) {
7571 verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
7572 verificationParams.getOriginatingUid());
7573 }
rich cannings13d428e2012-09-13 13:43:07 -07007574 if (verificationParams.getInstallerUid() >= 0) {
7575 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
7576 verificationParams.getInstallerUid());
7577 }
Kenny Root5ab21572011-07-27 11:11:19 -07007578 }
7579
Kenny Root05ca4c92011-09-15 10:36:25 -07007580 final PackageVerificationState verificationState = new PackageVerificationState(
7581 requiredUid, args);
7582
7583 mPendingVerification.append(verificationId, verificationState);
7584
7585 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
7586 receivers, verificationState);
Kenny Root5ab21572011-07-27 11:11:19 -07007587
7588 /*
Kenny Root05ca4c92011-09-15 10:36:25 -07007589 * If any sufficient verifiers were listed in the package
7590 * manifest, attempt to ask them.
Kenny Root5ab21572011-07-27 11:11:19 -07007591 */
Kenny Root05ca4c92011-09-15 10:36:25 -07007592 if (sufficientVerifiers != null) {
7593 final int N = sufficientVerifiers.size();
7594 if (N == 0) {
7595 Slog.i(TAG, "Additional verifiers required, but none installed.");
7596 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
7597 } else {
7598 for (int i = 0; i < N; i++) {
7599 final ComponentName verifierComponent = sufficientVerifiers.get(i);
7600
7601 final Intent sufficientIntent = new Intent(verification);
7602 sufficientIntent.setComponent(verifierComponent);
7603
rich canningsd55deb02012-10-02 14:53:08 -07007604 mContext.sendBroadcastAsUser(sufficientIntent, getUser());
Kenny Root05ca4c92011-09-15 10:36:25 -07007605 }
7606 }
7607 }
7608
7609 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
7610 mRequiredVerifierPackage, receivers);
7611 if (ret == PackageManager.INSTALL_SUCCEEDED
7612 && mRequiredVerifierPackage != null) {
7613 /*
7614 * Send the intent to the required verification agent,
7615 * but only start the verification timeout after the
7616 * target BroadcastReceivers have run.
7617 */
7618 verification.setComponent(requiredVerifierComponent);
rich canningsd55deb02012-10-02 14:53:08 -07007619 mContext.sendOrderedBroadcastAsUser(verification, getUser(),
Kenny Root05ca4c92011-09-15 10:36:25 -07007620 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
7621 new BroadcastReceiver() {
7622 @Override
7623 public void onReceive(Context context, Intent intent) {
7624 final Message msg = mHandler
7625 .obtainMessage(CHECK_PENDING_VERIFICATION);
7626 msg.arg1 = verificationId;
7627 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
7628 }
7629 }, null, 0, null, null);
7630
7631 /*
7632 * We don't want the copy to proceed until verification
7633 * succeeds, so null out this field.
7634 */
7635 mArgs = null;
7636 }
Kenny Root5ab21572011-07-27 11:11:19 -07007637 } else {
Kenny Root05ca4c92011-09-15 10:36:25 -07007638 /*
7639 * No package verification is enabled, so immediately start
7640 * the remote call to initiate copy using temporary file.
7641 */
Kenny Root5ab21572011-07-27 11:11:19 -07007642 ret = args.copyApk(mContainerService, true);
7643 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007644 }
Kenny Root5ab21572011-07-27 11:11:19 -07007645
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007646 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007647 }
7648
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007649 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007650 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07007651 // If mArgs is null, then MCS couldn't be reached. When it
7652 // reconnects, it will try again to install. At that point, this
7653 // will succeed.
7654 if (mArgs != null) {
7655 processPendingInstall(mArgs, mRet);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007656
Kenny Root0b2fa8c2012-09-14 10:26:16 -07007657 if (mTempPackage != null) {
7658 if (!mTempPackage.delete()) {
7659 Slog.w(TAG, "Couldn't delete temporary file: " +
7660 mTempPackage.getAbsolutePath());
7661 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007662 }
7663 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007664 }
7665
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007666 @Override
7667 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007668 mArgs = createInstallArgs(this);
7669 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007670 }
Kenny Root6dceb882012-04-12 14:23:49 -07007671
7672 public boolean isForwardLocked() {
7673 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
7674 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007675
7676 public Uri getPackageUri() {
7677 if (mTempPackage != null) {
7678 return Uri.fromFile(mTempPackage);
7679 } else {
7680 return mPackageURI;
7681 }
7682 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007683 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007684
7685 /*
7686 * Utility class used in movePackage api.
7687 * srcArgs and targetArgs are not set for invalid flags and make
7688 * sure to do null checks when invoking methods on them.
7689 * We probably want to return ErrorPrams for both failed installs
7690 * and moves.
7691 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007692 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007693 final IPackageMoveObserver observer;
7694 final int flags;
7695 final String packageName;
7696 final InstallArgs srcArgs;
7697 final InstallArgs targetArgs;
Kenny Root6dceb882012-04-12 14:23:49 -07007698 int uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007699 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07007700
7701 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
Amith Yamasani6ec10122012-08-23 13:49:25 -07007702 String packageName, String dataDir, int uid, UserHandle user) {
7703 super(user);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007704 this.srcArgs = srcArgs;
7705 this.observer = observer;
7706 this.flags = flags;
7707 this.packageName = packageName;
Kenny Root6dceb882012-04-12 14:23:49 -07007708 this.uid = uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007709 if (srcArgs != null) {
7710 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07007711 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007712 } else {
7713 targetArgs = null;
7714 }
7715 }
7716
Dianne Hackbornc895be72013-03-11 17:48:43 -07007717 @Override
7718 public String toString() {
7719 return "MoveParams{"
7720 + Integer.toHexString(System.identityHashCode(this))
7721 + " " + packageName + "}";
7722 }
7723
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007724 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007725 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7726 // Check for storage space on target medium
7727 if (!targetArgs.checkFreeStorage(mContainerService)) {
7728 Log.w(TAG, "Insufficient storage to install");
7729 return;
7730 }
Kenny Rootbf023582012-05-02 16:56:15 -07007731
7732 mRet = srcArgs.doPreCopy();
7733 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7734 return;
7735 }
7736
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007737 mRet = targetArgs.copyApk(mContainerService, false);
Kenny Rootbf023582012-05-02 16:56:15 -07007738 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7739 srcArgs.doPostCopy(uid);
7740 return;
7741 }
7742
7743 mRet = srcArgs.doPostCopy(uid);
7744 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7745 return;
7746 }
7747
7748 mRet = targetArgs.doPreInstall(mRet);
7749 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7750 return;
7751 }
7752
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007753 if (DEBUG_SD_INSTALL) {
7754 StringBuilder builder = new StringBuilder();
7755 if (srcArgs != null) {
7756 builder.append("src: ");
7757 builder.append(srcArgs.getCodePath());
7758 }
7759 if (targetArgs != null) {
7760 builder.append(" target : ");
7761 builder.append(targetArgs.getCodePath());
7762 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007763 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007764 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007765 }
7766
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007767 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007768 void handleReturnCode() {
Kenny Root6dceb882012-04-12 14:23:49 -07007769 targetArgs.doPostInstall(mRet, uid);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007770 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
7771 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
7772 currentStatus = PackageManager.MOVE_SUCCEEDED;
7773 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
7774 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
7775 }
7776 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007777 }
7778
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007779 @Override
7780 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007781 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007782 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007783 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007784
Kenny Root6dceb882012-04-12 14:23:49 -07007785 /**
7786 * Used during creation of InstallArgs
7787 *
7788 * @param flags package installation flags
7789 * @return true if should be installed on external storage
7790 */
7791 private static boolean installOnSd(int flags) {
7792 if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
7793 return false;
7794 }
7795 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
7796 return true;
7797 }
7798 return false;
7799 }
7800
7801 /**
7802 * Used during creation of InstallArgs
7803 *
7804 * @param flags package installation flags
7805 * @return true if should be installed as forward locked
7806 */
7807 private static boolean installForwardLocked(int flags) {
7808 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
7809 }
7810
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007811 private InstallArgs createInstallArgs(InstallParams params) {
Kenny Root6dceb882012-04-12 14:23:49 -07007812 if (installOnSd(params.flags) || params.isForwardLocked()) {
7813 return new AsecInstallArgs(params);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007814 } else {
7815 return new FileInstallArgs(params);
7816 }
7817 }
7818
Kenny Root85387d72010-08-26 10:13:11 -07007819 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
7820 String nativeLibraryPath) {
Kenny Root84e35ea2012-06-06 16:05:05 -07007821 final boolean isInAsec;
7822 if (installOnSd(flags)) {
7823 /* Apps on SD card are always in ASEC containers. */
7824 isInAsec = true;
7825 } else if (installForwardLocked(flags)
7826 && !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
7827 /*
7828 * Forward-locked apps are only in ASEC containers if they're the
7829 * new style
7830 */
7831 isInAsec = true;
7832 } else {
7833 isInAsec = false;
7834 }
7835
7836 if (isInAsec) {
Kenny Root6dceb882012-04-12 14:23:49 -07007837 return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07007838 installOnSd(flags), installForwardLocked(flags));
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007839 } else {
Kenny Root85387d72010-08-26 10:13:11 -07007840 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007841 }
7842 }
7843
Kenny Root85387d72010-08-26 10:13:11 -07007844 // Used by package mover
7845 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Kenny Root6dceb882012-04-12 14:23:49 -07007846 if (installOnSd(flags) || installForwardLocked(flags)) {
Kenny Rootbf023582012-05-02 16:56:15 -07007847 String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
7848 + AsecInstallArgs.RES_FILE_NAME);
7849 return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
7850 installForwardLocked(flags));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007851 } else {
Kenny Root85387d72010-08-26 10:13:11 -07007852 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007853 }
7854 }
7855
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007856 static abstract class InstallArgs {
7857 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007858 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007859 final int flags;
7860 final Uri packageURI;
7861 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07007862 final ManifestDigest manifestDigest;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007863 final UserHandle user;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007864
Kenny Root5ab21572011-07-27 11:11:19 -07007865 InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007866 String installerPackageName, ManifestDigest manifestDigest,
7867 UserHandle user) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007868 this.packageURI = packageURI;
7869 this.flags = flags;
7870 this.observer = observer;
7871 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07007872 this.manifestDigest = manifestDigest;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007873 this.user = user;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007874 }
7875
7876 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007877 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007878 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007879 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Kenny Root6dceb882012-04-12 14:23:49 -07007880
7881 abstract int doPostInstall(int status, int uid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007882 abstract String getCodePath();
7883 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07007884 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007885 // Need installer lock especially for dex file removal.
7886 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007887 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007888 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Kenny Root6dceb882012-04-12 14:23:49 -07007889
Kenny Rootbf023582012-05-02 16:56:15 -07007890 /**
7891 * Called before the source arguments are copied. This is used mostly
7892 * for MoveParams when it needs to read the source file to put it in the
7893 * destination.
7894 */
7895 int doPreCopy() {
7896 return PackageManager.INSTALL_SUCCEEDED;
7897 }
7898
7899 /**
7900 * Called after the source arguments are copied. This is used mostly for
7901 * MoveParams when it needs to read the source file to put it in the
7902 * destination.
7903 *
7904 * @return
7905 */
7906 int doPostCopy(int uid) {
7907 return PackageManager.INSTALL_SUCCEEDED;
7908 }
7909
Kenny Root6dceb882012-04-12 14:23:49 -07007910 protected boolean isFwdLocked() {
7911 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
7912 }
rich canningsd55deb02012-10-02 14:53:08 -07007913
7914 UserHandle getUser() {
7915 return user;
7916 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007917 }
7918
7919 class FileInstallArgs extends InstallArgs {
7920 File installDir;
7921 String codeFileName;
7922 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07007923 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007924 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007925
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007926 FileInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007927 super(params.getPackageUri(), params.observer, params.flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007928 params.installerPackageName, params.getManifestDigest(),
7929 params.getUser());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007930 }
7931
Kenny Root85387d72010-08-26 10:13:11 -07007932 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007933 super(null, null, 0, null, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007934 File codeFile = new File(fullCodePath);
7935 installDir = codeFile.getParentFile();
7936 codeFileName = fullCodePath;
7937 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07007938 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007939 }
7940
Kenny Root85387d72010-08-26 10:13:11 -07007941 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007942 super(packageURI, null, 0, null, null, null);
Kenny Root85387d72010-08-26 10:13:11 -07007943 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007944 String apkName = getNextCodePath(null, pkgName, ".apk");
7945 codeFileName = new File(installDir, apkName + ".apk").getPath();
7946 resourceFileName = getResourcePathFromCodePath();
Kenny Rootddbe50d2012-09-06 13:18:37 -07007947 libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007948 }
7949
Kenny Root11128572010-10-11 10:51:32 -07007950 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07007951 final long lowThreshold;
7952
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08007953 final DeviceStorageMonitorInternal
7954 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
Kenny Root62e1b4e2011-03-14 17:13:39 -07007955 if (dsm == null) {
7956 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
7957 lowThreshold = 0L;
7958 } else {
7959 if (dsm.isMemoryLow()) {
7960 Log.w(TAG, "Memory is reported as being too low; aborting package install");
7961 return false;
7962 }
7963
7964 lowThreshold = dsm.getMemoryLowThreshold();
7965 }
7966
Kenny Root11128572010-10-11 10:51:32 -07007967 try {
7968 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
7969 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07007970 return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07007971 } finally {
7972 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
7973 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007974 }
7975
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007976 String getCodePath() {
7977 return codeFileName;
7978 }
7979
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007980 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07007981 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007982 codeFileName = createTempPackageFile(installDir).getPath();
7983 resourceFileName = getResourcePathFromCodePath();
Kenny Rootddbe50d2012-09-06 13:18:37 -07007984 libraryPath = getLibraryPathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007985 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007986 }
7987
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007988 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007989 if (temp) {
7990 // Generate temp file name
7991 createCopyFile();
7992 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007993 // Get a ParcelFileDescriptor to write to the output file
7994 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007995 if (!created) {
7996 try {
7997 codeFile.createNewFile();
7998 // Set permissions
7999 if (!setPermissions()) {
8000 // Failed setting permissions.
8001 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8002 }
8003 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008004 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008005 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8006 }
8007 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008008 ParcelFileDescriptor out = null;
8009 try {
Kenny Root85387d72010-08-26 10:13:11 -07008010 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008011 } catch (FileNotFoundException e) {
Kenny Rootf5121a92011-08-10 16:23:32 -07008012 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008013 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8014 }
8015 // Copy the resource now
8016 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8017 try {
Kenny Root11128572010-10-11 10:51:32 -07008018 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
8019 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07008020 ret = imcs.copyResource(packageURI, null, out);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008021 } finally {
Kenny Root2782a472012-04-14 21:48:21 -07008022 IoUtils.closeQuietly(out);
Kenny Root11128572010-10-11 10:51:32 -07008023 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008024 }
Kenny Root85387d72010-08-26 10:13:11 -07008025
Kenny Root2782a472012-04-14 21:48:21 -07008026 if (isFwdLocked()) {
8027 final File destResourceFile = new File(getResourcePath());
8028
8029 // Copy the public files
8030 try {
8031 PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
8032 } catch (IOException e) {
8033 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
8034 + " forward-locked app.");
8035 destResourceFile.delete();
8036 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8037 }
8038 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07008039
8040 final File nativeLibraryFile = new File(getNativeLibraryPath());
8041 Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
8042 if (nativeLibraryFile.exists()) {
8043 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
8044 nativeLibraryFile.delete();
8045 }
8046 try {
8047 int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
8048 if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
8049 return copyRet;
8050 }
8051 } catch (IOException e) {
8052 Slog.e(TAG, "Copying native libraries failed", e);
8053 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
8054 }
8055
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008056 return ret;
8057 }
8058
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008059 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008060 if (status != PackageManager.INSTALL_SUCCEEDED) {
8061 cleanUp();
8062 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008063 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008064 }
8065
8066 boolean doRename(int status, final String pkgName, String oldCodePath) {
8067 if (status != PackageManager.INSTALL_SUCCEEDED) {
8068 cleanUp();
8069 return false;
8070 } else {
Kenny Root2782a472012-04-14 21:48:21 -07008071 final File oldCodeFile = new File(getCodePath());
8072 final File oldResourceFile = new File(getResourcePath());
Kenny Rootddbe50d2012-09-06 13:18:37 -07008073 final File oldLibraryFile = new File(getNativeLibraryPath());
Kenny Root2782a472012-04-14 21:48:21 -07008074
8075 // Rename APK file based on packageName
8076 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
8077 final File newCodeFile = new File(installDir, apkName + ".apk");
8078 if (!oldCodeFile.renameTo(newCodeFile)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008079 return false;
8080 }
Kenny Root2782a472012-04-14 21:48:21 -07008081 codeFileName = newCodeFile.getPath();
8082
8083 // Rename public resource file if it's forward-locked.
8084 final File newResFile = new File(getResourcePathFromCodePath());
8085 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
8086 return false;
8087 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07008088 resourceFileName = newResFile.getPath();
8089
8090 // Rename library path
8091 final File newLibraryFile = new File(getLibraryPathFromCodePath());
8092 if (newLibraryFile.exists()) {
8093 NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
8094 newLibraryFile.delete();
8095 }
8096 if (!oldLibraryFile.renameTo(newLibraryFile)) {
8097 Slog.e(TAG, "Cannot rename native library directory "
8098 + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
8099 return false;
8100 }
8101 libraryPath = newLibraryFile.getPath();
Kenny Root2782a472012-04-14 21:48:21 -07008102
8103 // Attempt to set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008104 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008105 return false;
8106 }
Kenny Root2782a472012-04-14 21:48:21 -07008107
rpcraig554cb0c2012-07-05 06:41:43 -04008108 if (!SELinux.restorecon(newCodeFile)) {
8109 return false;
8110 }
8111
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008112 return true;
8113 }
8114 }
8115
Kenny Root6dceb882012-04-12 14:23:49 -07008116 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008117 if (status != PackageManager.INSTALL_SUCCEEDED) {
8118 cleanUp();
8119 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008120 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008121 }
8122
8123 String getResourcePath() {
8124 return resourceFileName;
8125 }
8126
Kenny Root2782a472012-04-14 21:48:21 -07008127 private String getResourcePathFromCodePath() {
8128 final String codePath = getCodePath();
8129 if (isFwdLocked()) {
8130 final StringBuilder sb = new StringBuilder();
8131
8132 sb.append(mAppInstallDir.getPath());
8133 sb.append('/');
8134 sb.append(getApkName(codePath));
8135 sb.append(".zip");
8136
8137 /*
8138 * If our APK is a temporary file, mark the resource as a
8139 * temporary file as well so it can be cleaned up after
8140 * catastrophic failure.
8141 */
8142 if (codePath.endsWith(".tmp")) {
8143 sb.append(".tmp");
8144 }
8145
8146 return sb.toString();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008147 } else {
8148 return codePath;
8149 }
8150 }
8151
Kenny Rootddbe50d2012-09-06 13:18:37 -07008152 private String getLibraryPathFromCodePath() {
8153 return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
8154 }
8155
Kenny Root85387d72010-08-26 10:13:11 -07008156 @Override
8157 String getNativeLibraryPath() {
Kenny Rootddbe50d2012-09-06 13:18:37 -07008158 if (libraryPath == null) {
8159 libraryPath = getLibraryPathFromCodePath();
8160 }
Kenny Root85387d72010-08-26 10:13:11 -07008161 return libraryPath;
8162 }
8163
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008164 private boolean cleanUp() {
8165 boolean ret = true;
8166 String sourceDir = getCodePath();
8167 String publicSourceDir = getResourcePath();
8168 if (sourceDir != null) {
8169 File sourceFile = new File(sourceDir);
8170 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008171 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008172 ret = false;
8173 }
8174 // Delete application's code and resources
8175 sourceFile.delete();
8176 }
8177 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
8178 final File publicSourceFile = new File(publicSourceDir);
8179 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008180 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008181 }
8182 if (publicSourceFile.exists()) {
8183 publicSourceFile.delete();
8184 }
8185 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07008186
8187 if (libraryPath != null) {
8188 File nativeLibraryFile = new File(libraryPath);
8189 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
8190 if (!nativeLibraryFile.delete()) {
8191 Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
8192 }
8193 }
8194
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008195 return ret;
8196 }
8197
8198 void cleanUpResourcesLI() {
8199 String sourceDir = getCodePath();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008200 if (cleanUp()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008201 int retCode = mInstaller.rmdex(sourceDir);
8202 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008203 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008204 + " at location "
8205 + sourceDir + ", retcode=" + retCode);
8206 // we don't consider this to be a failure of the core package deletion
8207 }
8208 }
8209 }
8210
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008211 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008212 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07008213 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008214 final int filePermissions =
8215 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
8216 |FileUtils.S_IROTH;
8217 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
8218 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008219 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008220 getCodePath()
8221 + ". The return code was: " + retCode);
8222 // TODO Define new internal error
8223 return false;
8224 }
8225 return true;
8226 }
8227 return true;
8228 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008229
8230 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07008231 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008232 cleanUpResourcesLI();
8233 return true;
8234 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008235 }
8236
Kenny Root51a573c2012-05-17 13:30:28 -07008237 private boolean isAsecExternal(String cid) {
8238 final String asecPath = PackageHelper.getSdFilesystem(cid);
8239 return !asecPath.startsWith(mAsecInternalPath);
8240 }
8241
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008242 /**
8243 * Extract the MountService "container ID" from the full code path of an
8244 * .apk.
8245 */
8246 static String cidFromCodePath(String fullCodePath) {
8247 int eidx = fullCodePath.lastIndexOf("/");
8248 String subStr1 = fullCodePath.substring(0, eidx);
8249 int sidx = subStr1.lastIndexOf("/");
8250 return subStr1.substring(sidx+1, eidx);
8251 }
8252
Kenny Root6dceb882012-04-12 14:23:49 -07008253 class AsecInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008254 static final String RES_FILE_NAME = "pkg.apk";
Kenny Root6dceb882012-04-12 14:23:49 -07008255 static final String PUBLIC_RES_FILE_NAME = "res.zip";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008256
Kenny Root85387d72010-08-26 10:13:11 -07008257 String cid;
8258 String packagePath;
Kenny Root6dceb882012-04-12 14:23:49 -07008259 String resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07008260 String libraryPath;
8261
Kenny Root6dceb882012-04-12 14:23:49 -07008262 AsecInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07008263 super(params.getPackageUri(), params.observer, params.flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008264 params.installerPackageName, params.getManifestDigest(),
8265 params.getUser());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008266 }
8267
Kenny Root6dceb882012-04-12 14:23:49 -07008268 AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07008269 boolean isExternal, boolean isForwardLocked) {
8270 super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008271 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
8272 null, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008273 // Extract cid from fullCodePath
8274 int eidx = fullCodePath.lastIndexOf("/");
8275 String subStr1 = fullCodePath.substring(0, eidx);
8276 int sidx = subStr1.lastIndexOf("/");
8277 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07008278 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008279 }
8280
Kenny Rootc7a89992012-06-05 15:13:17 -07008281 AsecInstallArgs(String cid, boolean isForwardLocked) {
8282 super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008283 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
8284 null, null, null);
Dianne Hackbornaa77de12010-05-14 22:33:54 -07008285 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07008286 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008287 }
8288
Kenny Rootbf023582012-05-02 16:56:15 -07008289 AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
8290 super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008291 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
8292 null, null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008293 this.cid = cid;
8294 }
8295
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008296 void createCopyFile() {
8297 cid = getTempContainerId();
8298 }
8299
Kenny Root11128572010-10-11 10:51:32 -07008300 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
8301 try {
8302 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
8303 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07008304 return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07008305 } finally {
8306 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
8307 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08008308 }
8309
Kenny Root6dceb882012-04-12 14:23:49 -07008310 private final boolean isExternal() {
8311 return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
8312 }
8313
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008314 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008315 if (temp) {
8316 createCopyFile();
Kenny Rootf5121a92011-08-10 16:23:32 -07008317 } else {
8318 /*
8319 * Pre-emptively destroy the container since it's destroyed if
8320 * copying fails due to it existing anyway.
8321 */
8322 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008323 }
Kenny Root11128572010-10-11 10:51:32 -07008324
8325 final String newCachePath;
8326 try {
8327 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
8328 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07008329 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
8330 RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07008331 } finally {
8332 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
8333 }
8334
Kenny Root85387d72010-08-26 10:13:11 -07008335 if (newCachePath != null) {
8336 setCachePath(newCachePath);
8337 return PackageManager.INSTALL_SUCCEEDED;
8338 } else {
8339 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8340 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008341 }
8342
8343 @Override
8344 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07008345 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008346 }
8347
8348 @Override
8349 String getResourcePath() {
Kenny Root6dceb882012-04-12 14:23:49 -07008350 return resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07008351 }
8352
8353 @Override
8354 String getNativeLibraryPath() {
8355 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008356 }
8357
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008358 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008359 if (status != PackageManager.INSTALL_SUCCEEDED) {
8360 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008361 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008362 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008363 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008364 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07008365 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
8366 Process.SYSTEM_UID);
8367 if (newCachePath != null) {
8368 setCachePath(newCachePath);
8369 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008370 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8371 }
8372 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008373 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008374 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008375 }
8376
8377 boolean doRename(int status, final String pkgName,
8378 String oldCodePath) {
8379 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008380 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008381 if (PackageHelper.isContainerMounted(cid)) {
8382 // Unmount the container
8383 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008384 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008385 return false;
8386 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008387 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008388 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07008389 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
8390 " which might be stale. Will try to clean up.");
8391 // Clean up the stale container and proceed to recreate.
8392 if (!PackageHelper.destroySdDir(newCacheId)) {
8393 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
8394 return false;
8395 }
8396 // Successfully cleaned up stale container. Try to rename again.
8397 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
8398 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
8399 + " inspite of cleaning it up.");
8400 return false;
8401 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008402 }
8403 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008404 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008405 newCachePath = PackageHelper.mountSdDir(newCacheId,
8406 getEncryptKey(), Process.SYSTEM_UID);
8407 } else {
8408 newCachePath = PackageHelper.getSdDir(newCacheId);
8409 }
8410 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008411 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008412 return false;
8413 }
8414 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07008415 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008416 " at new path: " + newCachePath);
8417 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07008418 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008419 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008420 }
8421
Kenny Root85387d72010-08-26 10:13:11 -07008422 private void setCachePath(String newCachePath) {
8423 File cachePath = new File(newCachePath);
8424 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
8425 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
Kenny Root6dceb882012-04-12 14:23:49 -07008426
8427 if (isFwdLocked()) {
8428 resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
8429 } else {
8430 resourcePath = packagePath;
8431 }
Kenny Root85387d72010-08-26 10:13:11 -07008432 }
8433
Kenny Root6dceb882012-04-12 14:23:49 -07008434 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008435 if (status != PackageManager.INSTALL_SUCCEEDED) {
8436 cleanUp();
8437 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07008438 final int groupOwner;
8439 final String protectedFile;
8440 if (isFwdLocked()) {
Kenny Roote091f222012-09-11 15:01:26 -07008441 groupOwner = UserHandle.getSharedAppGid(uid);
Kenny Rootbf023582012-05-02 16:56:15 -07008442 protectedFile = RES_FILE_NAME;
8443 } else {
8444 groupOwner = -1;
8445 protectedFile = null;
8446 }
8447
Kenny Root6dceb882012-04-12 14:23:49 -07008448 if (uid < Process.FIRST_APPLICATION_UID
Kenny Rootbf023582012-05-02 16:56:15 -07008449 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Kenny Root6dceb882012-04-12 14:23:49 -07008450 Slog.e(TAG, "Failed to finalize " + cid);
8451 PackageHelper.destroySdDir(cid);
8452 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8453 }
8454
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008455 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008456 if (!mounted) {
Kenny Root6dceb882012-04-12 14:23:49 -07008457 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008458 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008459 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008460 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008461 }
8462
8463 private void cleanUp() {
Kenny Root6dceb882012-04-12 14:23:49 -07008464 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
8465
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008466 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008467 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008468 }
8469
8470 void cleanUpResourcesLI() {
8471 String sourceFile = getCodePath();
8472 // Remove dex file
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008473 int retCode = mInstaller.rmdex(sourceFile);
8474 if (retCode < 0) {
8475 Slog.w(TAG, "Couldn't remove dex file for package: "
8476 + " at location "
8477 + sourceFile.toString() + ", retcode=" + retCode);
8478 // we don't consider this to be a failure of the core package deletion
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008479 }
8480 cleanUp();
8481 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008482
8483 boolean matchContainer(String app) {
8484 if (cid.startsWith(app)) {
8485 return true;
8486 }
8487 return false;
8488 }
8489
8490 String getPackageName() {
Kenny Rootc7a89992012-06-05 15:13:17 -07008491 return getAsecPackageName(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008492 }
8493
8494 boolean doPostDeleteLI(boolean delete) {
8495 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008496 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008497 if (mounted) {
8498 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008499 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008500 }
8501 if (ret && delete) {
8502 cleanUpResourcesLI();
8503 }
8504 return ret;
8505 }
Kenny Rootbf023582012-05-02 16:56:15 -07008506
8507 @Override
8508 int doPreCopy() {
8509 if (isFwdLocked()) {
8510 if (!PackageHelper.fixSdPermissions(cid,
8511 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
8512 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8513 }
8514 }
8515
8516 return PackageManager.INSTALL_SUCCEEDED;
8517 }
8518
8519 @Override
8520 int doPostCopy(int uid) {
8521 if (isFwdLocked()) {
Kenny Rootbf023582012-05-02 16:56:15 -07008522 if (uid < Process.FIRST_APPLICATION_UID
Kenny Roote091f222012-09-11 15:01:26 -07008523 || !PackageHelper.fixSdPermissions(cid, UserHandle.getSharedAppGid(uid),
8524 RES_FILE_NAME)) {
Kenny Rootbf023582012-05-02 16:56:15 -07008525 Slog.e(TAG, "Failed to finalize " + cid);
8526 PackageHelper.destroySdDir(cid);
8527 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8528 }
8529 }
8530
8531 return PackageManager.INSTALL_SUCCEEDED;
8532 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008533 };
8534
Kenny Rootc7a89992012-06-05 15:13:17 -07008535 static String getAsecPackageName(String packageCid) {
8536 int idx = packageCid.lastIndexOf("-");
8537 if (idx == -1) {
8538 return packageCid;
8539 }
8540 return packageCid.substring(0, idx);
8541 }
8542
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008543 // Utility method used to create code paths based on package name and available index.
8544 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
8545 String idxStr = "";
8546 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008547 // Fall back to default value of idx=1 if prefix is not
8548 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008549 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00008550 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008551 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00008552 if (subStr.endsWith(suffix)) {
8553 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008554 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008555 // If oldCodePath already contains prefix find out the
8556 // ending index to either increment or decrement.
8557 int sidx = subStr.lastIndexOf(prefix);
8558 if (sidx != -1) {
8559 subStr = subStr.substring(sidx + prefix.length());
8560 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008561 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
8562 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008563 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008564 try {
8565 idx = Integer.parseInt(subStr);
8566 if (idx <= 1) {
8567 idx++;
8568 } else {
8569 idx--;
8570 }
8571 } catch(NumberFormatException e) {
8572 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008573 }
8574 }
8575 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008576 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008577 return prefix + idxStr;
8578 }
8579
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008580 // Utility method used to ignore ADD/REMOVE events
8581 // by directory observer.
8582 private static boolean ignoreCodePath(String fullPathStr) {
8583 String apkName = getApkName(fullPathStr);
8584 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
8585 if (idx != -1 && ((idx+1) < apkName.length())) {
8586 // Make sure the package ends with a numeral
8587 String version = apkName.substring(idx+1);
8588 try {
8589 Integer.parseInt(version);
8590 return true;
8591 } catch (NumberFormatException e) {}
8592 }
8593 return false;
8594 }
8595
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008596 // Utility method that returns the relative package path with respect
8597 // to the installation directory. Like say for /data/data/com.test-1.apk
8598 // string com.test-1 is returned.
8599 static String getApkName(String codePath) {
8600 if (codePath == null) {
8601 return null;
8602 }
8603 int sidx = codePath.lastIndexOf("/");
8604 int eidx = codePath.lastIndexOf(".");
8605 if (eidx == -1) {
8606 eidx = codePath.length();
8607 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008608 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008609 return null;
8610 }
8611 return codePath.substring(sidx+1, eidx);
8612 }
8613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 class PackageInstalledInfo {
8615 String name;
8616 int uid;
Dianne Hackborn786b4402012-08-27 15:14:02 -07008617 // The set of users that originally had this package installed.
8618 int[] origUsers;
8619 // The set of users that now have this package installed.
8620 int[] newUsers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008621 PackageParser.Package pkg;
8622 int returnCode;
8623 PackageRemovedInfo removedInfo;
8624 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 /*
8627 * Install a non-existing package.
8628 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008629 private void installNewPackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008630 int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02008631 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008633 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08008634
Dianne Hackbornc895be72013-03-11 17:48:43 -07008635 if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
Dave Burke383fa182012-10-23 23:12:19 -07008636 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07008638 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
8639 // A package with the same name is already installed, though
8640 // it has been renamed to an older name. The package we
8641 // are trying to install should be installed as an update to
8642 // the existing one, but that has not been requested, so bail.
8643 Slog.w(TAG, "Attempt to re-install " + pkgName
8644 + " without first uninstalling package running as "
8645 + mSettings.mRenamedPackages.get(pkgName));
8646 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
8647 return;
8648 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008649 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008651 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 + " without first uninstalling.");
8653 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
8654 return;
8655 }
8656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008658 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008659 System.currentTimeMillis(), user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008661 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008662 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
8663 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
8664 }
8665 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008666 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02008667 installerPackageName,
Christopher Tateacee6e92013-05-14 16:11:44 -07008668 null, null,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 res);
8670 // delete the partially installed application. the data directory will have to be
8671 // restored if it was already existing
8672 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
8673 // remove package from internal structures. Note that we want deletePackageX to
8674 // delete the package data and cache directories that it created in
8675 // scanPackageLocked, unless those directories existed before we even tried to
8676 // install.
Christopher Tateacee6e92013-05-14 16:11:44 -07008677 deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008678 dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008679 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 }
8681 }
8682 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008683
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008684 private void replacePackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008685 int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02008686 String installerPackageName, PackageInstalledInfo res) {
8687
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008688 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008689 String pkgName = pkg.packageName;
Christopher Tateacee6e92013-05-14 16:11:44 -07008690 int[] allUsers;
8691 boolean[] perUserInstalled;
8692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693 // First find the old package info and check signatures
8694 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008695 oldPackage = mPackages.get(pkgName);
Dianne Hackbornc895be72013-03-11 17:48:43 -07008696 if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
Kenny Root447106f2011-03-23 11:00:15 -07008697 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07008698 != PackageManager.SIGNATURE_MATCH) {
Kenny Root8c11f1d2012-04-14 12:10:38 -07008699 Slog.w(TAG, "New package has a different signature: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008700 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
8701 return;
8702 }
Christopher Tateacee6e92013-05-14 16:11:44 -07008703
8704 // In case of rollback, remember per-user/profile install state
8705 PackageSetting ps = mSettings.mPackages.get(pkgName);
8706 allUsers = sUserManager.getUserIds();
8707 perUserInstalled = new boolean[allUsers.length];
8708 for (int i = 0; i < allUsers.length; i++) {
Dianne Hackborn2c44c742013-05-17 12:07:21 -07008709 perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
Christopher Tateacee6e92013-05-14 16:11:44 -07008710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 }
Kenny Root85387d72010-08-26 10:13:11 -07008712 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008713 if (sysPkg) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008714 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
Christopher Tateacee6e92013-05-14 16:11:44 -07008715 user, allUsers, perUserInstalled, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 } else {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008717 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
Christopher Tateacee6e92013-05-14 16:11:44 -07008718 user, allUsers, perUserInstalled, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008719 }
8720 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008722 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008723 PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
Christopher Tateacee6e92013-05-14 16:11:44 -07008724 int[] allUsers, boolean[] perUserInstalled,
Jacek Surazski65e13172009-04-28 15:26:38 +02008725 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 PackageParser.Package newPackage = null;
8727 String pkgName = deletedPackage.packageName;
8728 boolean deletedPkg = true;
8729 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008730
Dianne Hackbornc895be72013-03-11 17:48:43 -07008731 if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
8732 + deletedPackage);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008733 long origUpdateTime;
8734 if (pkg.mExtras != null) {
8735 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
8736 } else {
8737 origUpdateTime = 0;
8738 }
8739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008740 // First delete the existing package while retaining the data directory
Christopher Tateacee6e92013-05-14 16:11:44 -07008741 if (!deletePackageLI(pkgName, null, true, null, null, PackageManager.DELETE_KEEP_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008742 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008743 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008744 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
8745 deletedPkg = false;
8746 } else {
8747 // Successfully deleted the old package. Now proceed with re-installation
8748 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008749 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008750 System.currentTimeMillis(), user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008751 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008752 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
8754 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08008755 }
8756 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008757 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02008758 installerPackageName,
Christopher Tateacee6e92013-05-14 16:11:44 -07008759 allUsers, perUserInstalled,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008760 res);
8761 updatedSettings = true;
8762 }
8763 }
8764
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008765 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008766 // remove package from internal structures. Note that we want deletePackageX to
8767 // delete the package data and cache directories that it created in
8768 // scanPackageLocked, unless those directories existed before we even tried to
8769 // install.
8770 if(updatedSettings) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07008771 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008772 deletePackageLI(
Christopher Tateacee6e92013-05-14 16:11:44 -07008773 pkgName, null, true, allUsers, perUserInstalled,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008774 PackageManager.DELETE_KEEP_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008775 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 }
8777 // Since we failed to install the new package we need to restore the old
8778 // package that we deleted.
8779 if(deletedPkg) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07008780 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07008781 File restoreFile = new File(deletedPackage.mPath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008782 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008783 boolean oldOnSd = isExternal(deletedPackage);
8784 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
8785 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
8786 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008787 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
8788 | SCAN_UPDATE_TIME;
8789 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
Dianne Hackborn786b4402012-08-27 15:14:02 -07008790 origUpdateTime, null) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008791 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
8792 return;
8793 }
8794 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07008795 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008796 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008797 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08008798 UPDATE_PERMISSIONS_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07008799 // can downgrade to reader
8800 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008801 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008802 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 }
8804 }
8805 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008808 PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
Christopher Tateacee6e92013-05-14 16:11:44 -07008809 int[] allUsers, boolean[] perUserInstalled,
Jacek Surazski65e13172009-04-28 15:26:38 +02008810 String installerPackageName, PackageInstalledInfo res) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07008811 if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
8812 + ", old=" + deletedPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 PackageParser.Package newPackage = null;
8814 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008815 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 PackageParser.PARSE_IS_SYSTEM;
Christopher Tate46eadae2013-06-26 14:20:18 -07008817 if ((deletedPackage.applicationInfo.flags&ApplicationInfo.FLAG_PRIVILEGED) != 0) {
8818 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
8819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008820 String packageName = deletedPackage.packageName;
8821 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
8822 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008823 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008824 return;
8825 }
8826 PackageParser.Package oldPkg;
8827 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07008828 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008829 synchronized (mPackages) {
8830 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008831 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008832 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
8833 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008834 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 return;
8836 }
8837 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008838
Dianne Hackborn21d9b562013-05-28 17:46:59 -07008839 killApplication(packageName, oldPkg.applicationInfo.uid, "replace sys pkg");
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008841 res.removedInfo.uid = oldPkg.applicationInfo.uid;
8842 res.removedInfo.removedPackage = packageName;
8843 // Remove existing system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008844 removePackageLI(oldPkgSetting, true);
Kenny Root447106f2011-03-23 11:00:15 -07008845 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08008846 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008847 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008848 // We didn't need to disable the .apk as a current system package,
8849 // which means we are replacing another update that is already
8850 // installed. We need to make sure to delete the older one's .apk.
Kenny Root6dceb882012-04-12 14:23:49 -07008851 res.removedInfo.args = createInstallArgs(0,
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008852 deletedPackage.applicationInfo.sourceDir,
8853 deletedPackage.applicationInfo.publicSourceDir,
8854 deletedPackage.applicationInfo.nativeLibraryDir);
8855 } else {
8856 res.removedInfo.args = null;
8857 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08008858 }
8859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 // Successfully disabled the old package. Now proceed with re-installation
8861 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
8862 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008863 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008865 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008866 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
8867 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
8868 }
8869 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008870 if (newPackage.mExtras != null) {
8871 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
8872 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
8873 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
8874 }
Christopher Tateacee6e92013-05-14 16:11:44 -07008875 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008876 updatedSettings = true;
8877 }
8878
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008879 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008880 // Re installation failed. Restore old information
8881 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07008882 if (newPackage != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008883 removeInstalledPackageLI(newPackage, true);
Dianne Hackborn62da8462009-05-13 15:06:13 -07008884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 // Add back the old system package
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008886 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 // Restore the old system information in Settings
8888 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008889 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07008890 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02008891 mSettings.setInstallerPackageName(packageName,
8892 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 }
Kenny Root447106f2011-03-23 11:00:15 -07008894 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 }
8896 }
8897 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008898
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008899 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008900 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008901 int retCode;
8902 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
8903 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
8904 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07008905 if (mNoDexOpt) {
8906 /*
8907 * If we're in an engineering build, programs are lazily run
8908 * through dexopt. If the .dex file doesn't exist yet, it
8909 * will be created when the program is run next.
8910 */
8911 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
8912 } else {
8913 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
8914 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8915 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008916 }
8917 }
8918 return PackageManager.INSTALL_SUCCEEDED;
8919 }
8920
Christopher Tateacee6e92013-05-14 16:11:44 -07008921 private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
8922 int[] allUsers, boolean[] perUserInstalled,
8923 PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008924 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008925 synchronized (mPackages) {
8926 //write settings. the installStatus will be incomplete at this stage.
8927 //note that the new package setting would have already been
8928 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07008929 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07008930 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 }
8932
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008933 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008934 != PackageManager.INSTALL_SUCCEEDED) {
8935 // Discontinue if moving dex files failed.
8936 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 }
Kenny Root6dceb882012-04-12 14:23:49 -07008938
Dianne Hackbornc895be72013-03-11 17:48:43 -07008939 if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.mPath);
Kenny Root6dceb882012-04-12 14:23:49 -07008940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008941 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008942 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08008943 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
8944 ? UPDATE_PERMISSIONS_ALL : 0));
Christopher Tate32a019d2013-04-04 15:40:04 -07008945 // For system-bundled packages, we assume that installing an upgraded version
8946 // of the package implies that the user actually wants to run that new code,
8947 // so we enable the package.
8948 if (isSystemApp(newPackage)) {
8949 // NB: implicit assumption that system package upgrades apply to all users
8950 if (DEBUG_INSTALL) {
8951 Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName);
8952 }
8953 PackageSetting ps = mSettings.mPackages.get(pkgName);
8954 if (ps != null) {
8955 if (res.origUsers != null) {
8956 for (int userHandle : res.origUsers) {
8957 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT,
8958 userHandle, installerPackageName);
8959 }
8960 }
Christopher Tateacee6e92013-05-14 16:11:44 -07008961 // Also convey the prior install/uninstall state
8962 if (allUsers != null && perUserInstalled != null) {
8963 for (int i = 0; i < allUsers.length; i++) {
8964 if (DEBUG_INSTALL) {
8965 Slog.d(TAG, " user " + allUsers[i]
8966 + " => " + perUserInstalled[i]);
8967 }
8968 ps.setInstalled(perUserInstalled[i], allUsers[i]);
8969 }
8970 // these install state changes will be persisted in the
8971 // upcoming call to mSettings.writeLPr().
8972 }
Christopher Tate32a019d2013-04-04 15:40:04 -07008973 }
8974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 res.name = pkgName;
8976 res.uid = newPackage.applicationInfo.uid;
8977 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07008978 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02008979 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008980 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
8981 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07008982 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 }
8984 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008985
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008986 private void installPackageLI(InstallArgs args,
8987 boolean newInstall, PackageInstalledInfo res) {
8988 int pFlags = args.flags;
8989 String installerPackageName = args.installerPackageName;
8990 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008991 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08008992 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008993 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008994 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008995 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07008996 // Result object to be returned
8997 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
8998
Dianne Hackbornc895be72013-03-11 17:48:43 -07008999 if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009000 // Retrieve PackageSettings and parse package
Kenny Root6dceb882012-04-12 14:23:49 -07009001 int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
9002 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
9003 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009004 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
9005 pp.setSeparateProcesses(mSeparateProcesses);
9006 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
9007 null, mMetrics, parseFlags);
9008 if (pkg == null) {
9009 res.returnCode = pp.getParseError();
9010 return;
9011 }
9012 String pkgName = res.name = pkg.packageName;
9013 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
9014 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
9015 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
9016 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009017 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009018 }
9019 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
9020 res.returnCode = pp.getParseError();
9021 return;
9022 }
Kenny Root5ab21572011-07-27 11:11:19 -07009023
9024 /* If the installer passed in a manifest digest, compare it now. */
9025 if (args.manifestDigest != null) {
9026 if (DEBUG_INSTALL) {
9027 final String parsedManifest = pkg.manifestDigest == null ? "null"
9028 : pkg.manifestDigest.toString();
9029 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
9030 + parsedManifest);
9031 }
9032
9033 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
9034 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
9035 return;
9036 }
9037 } else if (DEBUG_INSTALL) {
9038 final String parsedManifest = pkg.manifestDigest == null
9039 ? "null" : pkg.manifestDigest.toString();
9040 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
9041 }
9042
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009043 // Get rid of all references to package scan path via parser.
9044 pp = null;
9045 String oldCodePath = null;
9046 boolean systemApp = false;
9047 synchronized (mPackages) {
9048 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009049 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
9050 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08009051 if (pkg.mOriginalPackages != null
9052 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009053 && mPackages.containsKey(oldName)) {
9054 // This package is derived from an original package,
9055 // and this device has been updating from that original
9056 // name. We must continue using the original name, so
9057 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08009058 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009059 pkgName = pkg.packageName;
9060 replace = true;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009061 if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
9062 + oldName + " pkgName=" + pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009063 } else if (mPackages.containsKey(pkgName)) {
9064 // This package, under its official name, already exists
9065 // on the device; we should replace it.
9066 replace = true;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009067 if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009068 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009069 }
9070 PackageSetting ps = mSettings.mPackages.get(pkgName);
9071 if (ps != null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009072 if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009073 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
9074 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
9075 systemApp = (ps.pkg.applicationInfo.flags &
9076 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07009077 }
Dianne Hackborn786b4402012-08-27 15:14:02 -07009078 res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
Dianne Hackbornade3eca2009-05-11 18:54:45 -07009079 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009080 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009081
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009082 if (systemApp && onSd) {
9083 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009084 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009085 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
9086 return;
9087 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08009088
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009089 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
9090 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
9091 return;
9092 }
9093 // Set application objects path explicitly after the rename
9094 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07009095 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009096 if (replace) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009097 replacePackageLI(pkg, parseFlags, scanMode, args.user,
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009098 installerPackageName, res);
9099 } else {
Narayan Kamath65048bd2013-12-16 18:18:12 +00009100 installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,
Dianne Hackborn786b4402012-08-27 15:14:02 -07009101 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009103 synchronized (mPackages) {
Dianne Hackborn786b4402012-08-27 15:14:02 -07009104 final PackageSetting ps = mSettings.mPackages.get(pkgName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009105 if (ps != null) {
Dianne Hackborn786b4402012-08-27 15:14:02 -07009106 res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009107 }
9108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009110
Kenny Root85387d72010-08-26 10:13:11 -07009111 private static boolean isForwardLocked(PackageParser.Package pkg) {
9112 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 }
9114
Kenny Root88670d82012-05-09 15:47:35 -07009115
9116 private boolean isForwardLocked(PackageSetting ps) {
9117 return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
9118 }
9119
Kenny Root85387d72010-08-26 10:13:11 -07009120 private static boolean isExternal(PackageParser.Package pkg) {
9121 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
9122 }
9123
Kenny Root6dceb882012-04-12 14:23:49 -07009124 private static boolean isExternal(PackageSetting ps) {
9125 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
9126 }
9127
Kenny Root85387d72010-08-26 10:13:11 -07009128 private static boolean isSystemApp(PackageParser.Package pkg) {
9129 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
9130 }
9131
Christopher Tateccbf84f2013-05-08 15:25:41 -07009132 private static boolean isPrivilegedApp(PackageParser.Package pkg) {
9133 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
9134 }
9135
Kenny Root502e9a42011-01-10 13:48:15 -08009136 private static boolean isSystemApp(ApplicationInfo info) {
9137 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
9138 }
9139
Kenny Root208d3412012-05-07 19:42:35 -07009140 private static boolean isSystemApp(PackageSetting ps) {
9141 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
9142 }
9143
Nick Kralevich60792852013-04-03 14:12:24 -07009144 private static boolean isUpdatedSystemApp(PackageSetting ps) {
9145 return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
9146 }
9147
Kenny Root85387d72010-08-26 10:13:11 -07009148 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
9149 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009150 }
9151
Kenny Root88670d82012-05-09 15:47:35 -07009152 private int packageFlagsToInstallFlags(PackageSetting ps) {
9153 int installFlags = 0;
9154 if (isExternal(ps)) {
9155 installFlags |= PackageManager.INSTALL_EXTERNAL;
9156 }
9157 if (isForwardLocked(ps)) {
9158 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
9159 }
9160 return installFlags;
9161 }
9162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 private void deleteTempPackageFiles() {
Kenny Root0b2fa8c2012-09-14 10:26:16 -07009164 final FilenameFilter filter = new FilenameFilter() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 public boolean accept(File dir, String name) {
9166 return name.startsWith("vmdl") && name.endsWith(".tmp");
9167 }
9168 };
Kenny Root0b2fa8c2012-09-14 10:26:16 -07009169 deleteTempPackageFilesInDirectory(mAppInstallDir, filter);
9170 deleteTempPackageFilesInDirectory(mDrmAppPrivateInstallDir, filter);
9171 }
9172
9173 private static final void deleteTempPackageFilesInDirectory(File directory,
9174 FilenameFilter filter) {
9175 final String[] tmpFilesList = directory.list(filter);
9176 if (tmpFilesList == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 return;
9178 }
Kenny Root0b2fa8c2012-09-14 10:26:16 -07009179 for (int i = 0; i < tmpFilesList.length; i++) {
9180 final File tmpFile = new File(directory, tmpFilesList[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 tmpFile.delete();
9182 }
9183 }
9184
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009185 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 File tmpPackageFile;
9187 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009188 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009190 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009191 return null;
9192 }
9193 try {
9194 FileUtils.setPermissions(
9195 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
9196 -1, -1);
rpcraig554cb0c2012-07-05 06:41:43 -04009197 if (!SELinux.restorecon(tmpPackageFile)) {
9198 return null;
9199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009200 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009201 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 return null;
9203 }
9204 return tmpPackageFile;
9205 }
9206
Amith Yamasani67df64b2012-12-14 12:09:36 -08009207 @Override
9208 public void deletePackageAsUser(final String packageName,
9209 final IPackageDeleteObserver observer,
9210 final int userId, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 mContext.enforceCallingOrSelfPermission(
9212 android.Manifest.permission.DELETE_PACKAGES, null);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009213 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08009214 if (UserHandle.getUserId(uid) != userId) {
9215 mContext.enforceCallingPermission(
9216 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
9217 "deletePackage for user " + userId);
9218 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07009219 if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08009220 try {
9221 observer.packageDeleted(packageName, PackageManager.DELETE_FAILED_USER_RESTRICTED);
9222 } catch (RemoteException re) {
9223 }
9224 return;
9225 }
9226
Dianne Hackbornc895be72013-03-11 17:48:43 -07009227 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
Amith Yamasani67df64b2012-12-14 12:09:36 -08009228 // Queue up an async operation since the package deletion may take a little while.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229 mHandler.post(new Runnable() {
9230 public void run() {
9231 mHandler.removeCallbacks(this);
Amith Yamasani67df64b2012-12-14 12:09:36 -08009232 final int returnCode = deletePackageX(packageName, userId, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 if (observer != null) {
9234 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08009235 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 } catch (RemoteException e) {
9237 Log.i(TAG, "Observer no longer exists.");
9238 } //end catch
9239 } //end if
9240 } //end run
9241 });
9242 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009243
Amith Yamasani655d0e22013-06-12 14:19:10 -07009244 private boolean isPackageDeviceAdmin(String packageName, int userId) {
9245 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
9246 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
9247 try {
9248 if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
9249 || dpm.isDeviceOwner(packageName))) {
9250 return true;
9251 }
9252 } catch (RemoteException e) {
9253 }
9254 return false;
9255 }
9256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 /**
9258 * This method is an internal method that could be get invoked either
9259 * to delete an installed package or to clean up a failed installation.
9260 * After deleting an installed package, a broadcast is sent to notify any
9261 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009262 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 * installation wouldn't have sent the initial broadcast either
9264 * The key steps in deleting a package are
9265 * deleting the package information in internal structures like mPackages,
9266 * deleting the packages base directories through installd
9267 * updating mSettings to reflect current status
9268 * persisting settings for later use
9269 * sending a broadcast if necessary
9270 */
Amith Yamasani67df64b2012-12-14 12:09:36 -08009271 private int deletePackageX(String packageName, int userId, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08009272 final PackageRemovedInfo info = new PackageRemovedInfo();
9273 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274
Amith Yamasani655d0e22013-06-12 14:19:10 -07009275 if (isPackageDeviceAdmin(packageName, userId)) {
9276 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
9277 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009278 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07009279
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009280 boolean removedForAllUsers = false;
9281 boolean systemUpdate = false;
Christopher Tateacee6e92013-05-14 16:11:44 -07009282
9283 // for the uninstall-updates case and restricted profiles, remember the per-
9284 // userhandle installed state
9285 int[] allUsers;
9286 boolean[] perUserInstalled;
9287 synchronized (mPackages) {
9288 PackageSetting ps = mSettings.mPackages.get(packageName);
9289 allUsers = sUserManager.getUserIds();
9290 perUserInstalled = new boolean[allUsers.length];
9291 for (int i = 0; i < allUsers.length; i++) {
Dianne Hackborn2c44c742013-05-17 12:07:21 -07009292 perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
Christopher Tateacee6e92013-05-14 16:11:44 -07009293 }
9294 }
9295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 synchronized (mInstallLock) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009297 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009298 res = deletePackageLI(packageName,
9299 (flags & PackageManager.DELETE_ALL_USERS) != 0
Amith Yamasani67df64b2012-12-14 12:09:36 -08009300 ? UserHandle.ALL : new UserHandle(userId),
Christopher Tateacee6e92013-05-14 16:11:44 -07009301 true, allUsers, perUserInstalled,
9302 flags | REMOVE_CHATTY, info, true);
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009303 systemUpdate = info.isRemovedPackageSystemUpdate;
9304 if (res && !systemUpdate && mPackages.get(packageName) == null) {
9305 removedForAllUsers = true;
9306 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009307 if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate
9308 + " removedForAllUsers=" + removedForAllUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009310
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009311 if (res) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009312 info.sendBroadcast(true, systemUpdate, removedForAllUsers);
Romain Guy96f43572009-03-24 20:27:49 -07009313
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009314 // If the removed package was a system update, the old system package
Romain Guy96f43572009-03-24 20:27:49 -07009315 // was re-enabled; we need to broadcast this information
9316 if (systemUpdate) {
9317 Bundle extras = new Bundle(1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009318 extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
9319 ? info.removedAppId : info.uid);
Romain Guy96f43572009-03-24 20:27:49 -07009320 extras.putBoolean(Intent.EXTRA_REPLACING, true);
9321
Dianne Hackborne7f97212011-02-24 14:40:20 -08009322 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009323 extras, null, null, null);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009324 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009325 extras, null, null, null);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009326 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009327 null, packageName, null, null);
Romain Guy96f43572009-03-24 20:27:49 -07009328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009329 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07009330 // Force a gc here.
9331 Runtime.getRuntime().gc();
9332 // Delete the resources here after sending the broadcast to let
9333 // other processes clean up before deleting resources.
9334 if (info.args != null) {
9335 synchronized (mInstallLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009336 info.args.doPostDeleteLI(true);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07009337 }
9338 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08009339
9340 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 }
9342
9343 static class PackageRemovedInfo {
9344 String removedPackage;
9345 int uid = -1;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009346 int removedAppId = -1;
9347 int[] removedUsers = null;
Romain Guy96f43572009-03-24 20:27:49 -07009348 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009349 // Clean up resources deleted packages.
9350 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07009351
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009352 void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009353 Bundle extras = new Bundle(1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009354 extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009355 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
9356 if (replacing) {
9357 extras.putBoolean(Intent.EXTRA_REPLACING, true);
9358 }
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009359 extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08009361 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009362 extras, null, null, removedUsers);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07009363 if (fullRemove && !replacing) {
9364 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009365 extras, null, null, removedUsers);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07009366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009367 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009368 if (removedAppId >= 0) {
Amith Yamasani13593602012-03-22 16:16:17 -07009369 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009370 removedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 }
9372 }
9373 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 /*
9376 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
9377 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009378 * make sure this flag is set for partially installed apps. If not its meaningless to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 * delete a partially installed application.
9380 */
Christopher Tateacee6e92013-05-14 16:11:44 -07009381 private void removePackageDataLI(PackageSetting ps,
9382 int[] allUserHandles, boolean[] perUserInstalled,
9383 PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009384 String packageName = ps.name;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009385 if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009386 removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07009388 final PackageSetting deletedPs;
9389 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009390 synchronized (mPackages) {
9391 deletedPs = mSettings.mPackages.get(packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009392 if (outInfo != null) {
9393 outInfo.removedPackage = packageName;
9394 outInfo.removedUsers = deletedPs != null
Dianne Hackborn786b4402012-08-27 15:14:02 -07009395 ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
9396 : null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009398 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009399 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
Dianne Hackborn4428e172012-08-24 17:43:05 -07009400 removeDataDirsLI(packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009401 schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402 }
Kenny Root447106f2011-03-23 11:00:15 -07009403 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08009405 if (deletedPs != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009406 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009407 if (outInfo != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009408 outInfo.removedAppId = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009409 }
9410 if (deletedPs != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08009411 updatePermissionsLPw(deletedPs.name, null, 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009412 if (deletedPs.sharedUser != null) {
9413 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07009414 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009415 }
9416 }
Amith Yamasania3f133a2012-08-09 17:11:28 -07009417 clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08009418 }
Christopher Tateacee6e92013-05-14 16:11:44 -07009419 // make sure to preserve per-user disabled state if this removal was just
9420 // a downgrade of a system app to the factory package
9421 if (allUserHandles != null && perUserInstalled != null) {
9422 if (DEBUG_REMOVE) {
9423 Slog.d(TAG, "Propagating install state across downgrade");
9424 }
9425 for (int i = 0; i < allUserHandles.length; i++) {
9426 if (DEBUG_REMOVE) {
9427 Slog.d(TAG, " user " + allUserHandles[i]
9428 + " => " + perUserInstalled[i]);
9429 }
9430 ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
9431 }
9432 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08009433 }
Kenny Root447106f2011-03-23 11:00:15 -07009434 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009435 if (writeSettings) {
9436 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07009437 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009439 }
Kenny Root3b9933d2013-04-08 16:05:00 -07009440 if (outInfo != null) {
9441 // A user ID was deleted here. Go through all users and remove it
9442 // from KeyStore.
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009443 removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId);
Kenny Rootd72317a2013-04-01 15:59:59 -07009444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009445 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009446
Christopher Tate628946a2013-10-18 18:11:05 -07009447 static boolean locationIsPrivileged(File path) {
Christopher Tate0fe85a92013-10-04 19:40:09 -07009448 try {
9449 final String privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app")
9450 .getCanonicalPath();
9451 return path.getCanonicalPath().startsWith(privilegedAppDir);
9452 } catch (IOException e) {
9453 Slog.e(TAG, "Unable to access code path " + path);
9454 }
9455 return false;
9456 }
9457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009458 /*
9459 * Tries to delete system package.
9460 */
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009461 private boolean deleteSystemPackageLI(PackageSetting newPs,
Christopher Tateacee6e92013-05-14 16:11:44 -07009462 int[] allUserHandles, boolean[] perUserInstalled,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009463 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
Christopher Tateacee6e92013-05-14 16:11:44 -07009464 final boolean applyUserRestrictions
9465 = (allUserHandles != null) && (perUserInstalled != null);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009466 PackageSetting disabledPs = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009467 // Confirm if the system package has been updated
9468 // An updated system app can be deleted. This will also have to restore
9469 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07009470 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 synchronized (mPackages) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009472 disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009474 if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + newPs
9475 + " disabledPs=" + disabledPs);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009476 if (disabledPs == null) {
9477 Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009478 return false;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009479 } else if (DEBUG_REMOVE) {
9480 Slog.d(TAG, "Deleting system pkg from data partition");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 }
Christopher Tateacee6e92013-05-14 16:11:44 -07009482 if (DEBUG_REMOVE) {
9483 if (applyUserRestrictions) {
9484 Slog.d(TAG, "Remembering install states:");
9485 for (int i = 0; i < allUserHandles.length; i++) {
9486 Slog.d(TAG, " u=" + allUserHandles[i] + " inst=" + perUserInstalled[i]);
9487 }
9488 }
9489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07009491 outInfo.isRemovedPackageSystemUpdate = true;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009492 if (disabledPs.versionCode < newPs.versionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08009493 // Delete data for downgrades
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009494 flags &= ~PackageManager.DELETE_KEEP_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009495 } else {
9496 // Preserve data by setting flag
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009497 flags |= PackageManager.DELETE_KEEP_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009498 }
Christopher Tateacee6e92013-05-14 16:11:44 -07009499 boolean ret = deleteInstalledPackageLI(newPs, true, flags,
9500 allUserHandles, perUserInstalled, outInfo, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009501 if (!ret) {
9502 return false;
9503 }
Kenny Root447106f2011-03-23 11:00:15 -07009504 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009505 synchronized (mPackages) {
9506 // Reinstate the old system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009507 mSettings.enableSystemPackageLPw(newPs.name);
Kenny Root8f7cc022010-09-12 09:04:56 -07009508 // Remove any native libraries from the upgraded package.
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009509 NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009510 }
9511 // Install the system package
Dianne Hackbornc895be72013-03-11 17:48:43 -07009512 if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
Christopher Tate0fe85a92013-10-04 19:40:09 -07009513 int parseFlags = PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM;
9514 if (locationIsPrivileged(disabledPs.codePath)) {
9515 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
9516 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009517 PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
Christopher Tate0fe85a92013-10-04 19:40:09 -07009518 parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 if (newPkg == null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009521 Slog.w(TAG, "Failed to restore system package:" + newPs.name
9522 + " with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 return false;
9524 }
Kenny Root447106f2011-03-23 11:00:15 -07009525 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009526 synchronized (mPackages) {
Dianne Hackborne639da72012-02-21 15:11:13 -08009527 updatePermissionsLPw(newPkg.packageName, newPkg,
9528 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
Christopher Tateacee6e92013-05-14 16:11:44 -07009529 if (applyUserRestrictions) {
9530 if (DEBUG_REMOVE) {
9531 Slog.d(TAG, "Propagating install state across reinstall");
9532 }
9533 PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
9534 for (int i = 0; i < allUserHandles.length; i++) {
9535 if (DEBUG_REMOVE) {
9536 Slog.d(TAG, " user " + allUserHandles[i]
9537 + " => " + perUserInstalled[i]);
9538 }
9539 ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
9540 }
9541 // Regardless of writeSettings we need to ensure that this restriction
9542 // state propagation is persisted
9543 mSettings.writeAllUsersPackageRestrictionsLPr();
9544 }
Kenny Root447106f2011-03-23 11:00:15 -07009545 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009546 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07009547 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009549 }
9550 return true;
9551 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07009552
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009553 private boolean deleteInstalledPackageLI(PackageSetting ps,
Christopher Tateacee6e92013-05-14 16:11:44 -07009554 boolean deleteCodeAndResources, int flags,
9555 int[] allUserHandles, boolean[] perUserInstalled,
9556 PackageRemovedInfo outInfo, boolean writeSettings) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07009557 if (outInfo != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009558 outInfo.uid = ps.appId;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07009559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009560
9561 // Delete package data from internal structures and also remove data if flag is set
Christopher Tateacee6e92013-05-14 16:11:44 -07009562 removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009563
9564 // Delete application code and resources
Kenny Root92bc9b32012-10-23 17:42:40 -07009565 if (deleteCodeAndResources && (outInfo != null)) {
Kenny Root5455f682012-09-09 14:52:10 -07009566 outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009567 ps.resourcePathString, ps.nativeLibraryPathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 }
9569 return true;
9570 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 /*
9573 * This method handles package deletion in general
9574 */
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009575 private boolean deletePackageLI(String packageName, UserHandle user,
Christopher Tateacee6e92013-05-14 16:11:44 -07009576 boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,
9577 int flags, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009578 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009579 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009580 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009581 return false;
9582 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009583 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009584 PackageSetting ps;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585 boolean dataOnly = false;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009586 int removeUser = -1;
9587 int appId = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 synchronized (mPackages) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009589 ps = mSettings.mPackages.get(packageName);
9590 if (ps == null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009591 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
9592 return false;
9593 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009594 if ((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009595 && user.getIdentifier() != UserHandle.USER_ALL) {
9596 // The caller is asking that the package only be deleted for a single
9597 // user. To do this, we just mark its uninstalled state and delete
Dianne Hackbornc895be72013-03-11 17:48:43 -07009598 // its data. If this is a system app, we only allow this to happen if
9599 // they have set the special DELETE_SYSTEM_APP which requests different
9600 // semantics than normal for uninstalling system apps.
9601 if (DEBUG_REMOVE) Slog.d(TAG, "Only deleting for single user");
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009602 ps.setUserState(user.getIdentifier(),
9603 COMPONENT_ENABLED_STATE_DEFAULT,
9604 false, //installed
9605 true, //stopped
9606 true, //notLaunched
Amith Yamasani655d0e22013-06-12 14:19:10 -07009607 false, //blocked
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -07009608 null, null, null);
Amith Yamasani67df64b2012-12-14 12:09:36 -08009609 if (!isSystemApp(ps)) {
9610 if (ps.isAnyInstalled(sUserManager.getUserIds())) {
9611 // Other user still have this package installed, so all
9612 // we need to do is clear this user's data and save that
9613 // it is uninstalled.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009614 if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
Amith Yamasani67df64b2012-12-14 12:09:36 -08009615 removeUser = user.getIdentifier();
9616 appId = ps.appId;
9617 mSettings.writePackageRestrictionsLPr(removeUser);
9618 } else {
9619 // We need to set it back to 'installed' so the uninstall
9620 // broadcasts will be sent correctly.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009621 if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
Amith Yamasani67df64b2012-12-14 12:09:36 -08009622 ps.setInstalled(true, user.getIdentifier());
9623 }
9624 } else {
9625 // This is a system app, so we assume that the
9626 // other users still have this package installed, so all
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009627 // we need to do is clear this user's data and save that
9628 // it is uninstalled.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009629 if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009630 removeUser = user.getIdentifier();
9631 appId = ps.appId;
9632 mSettings.writePackageRestrictionsLPr(removeUser);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009633 }
9634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009636
9637 if (removeUser >= 0) {
9638 // From above, we determined that we are deleting this only
9639 // for a single user. Continue the work here.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009640 if (DEBUG_REMOVE) Slog.d(TAG, "Updating install state for user: " + removeUser);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009641 if (outInfo != null) {
9642 outInfo.removedPackage = packageName;
9643 outInfo.removedAppId = appId;
9644 outInfo.removedUsers = new int[] {removeUser};
9645 }
9646 mInstaller.clearUserData(packageName, removeUser);
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009647 removeKeystoreDataIfNeeded(removeUser, appId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009648 schedulePackageCleaning(packageName, removeUser, false);
9649 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 if (dataOnly) {
9653 // Delete application data first
Dianne Hackbornc895be72013-03-11 17:48:43 -07009654 if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
Christopher Tateacee6e92013-05-14 16:11:44 -07009655 removePackageDataLI(ps, null, null, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656 return true;
9657 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08009658
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009659 boolean ret = false;
Geremy Condraf1bcca82013-01-07 22:35:24 -08009660 mSettings.mKeySetManager.removeAppKeySetData(packageName);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009661 if (isSystemApp(ps)) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009662 if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009663 // When an updated system application is deleted we delete the existing resources as well and
9664 // fall back to existing code in system partition
Christopher Tateacee6e92013-05-14 16:11:44 -07009665 ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,
9666 flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009667 } else {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009668 if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009669 // Kill application pre-emptively especially for apps on sd.
Dianne Hackborn21d9b562013-05-28 17:46:59 -07009670 killApplication(packageName, ps.appId, "uninstall pkg");
Christopher Tateacee6e92013-05-14 16:11:44 -07009671 ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,
9672 allUserHandles, perUserInstalled,
9673 outInfo, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009674 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08009675
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009676 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009678
Dianne Hackborn183ce022012-06-29 15:00:21 -07009679 private final class ClearStorageConnection implements ServiceConnection {
9680 IMediaContainerService mContainerService;
9681
9682 @Override
9683 public void onServiceConnected(ComponentName name, IBinder service) {
9684 synchronized (this) {
9685 mContainerService = IMediaContainerService.Stub.asInterface(service);
9686 notifyAll();
9687 }
9688 }
9689
9690 @Override
9691 public void onServiceDisconnected(ComponentName name) {
9692 }
9693 }
9694
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009695 private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
Dianne Hackborn183ce022012-06-29 15:00:21 -07009696 final boolean mounted;
9697 if (Environment.isExternalStorageEmulated()) {
9698 mounted = true;
9699 } else {
9700 final String status = Environment.getExternalStorageState();
9701
9702 mounted = status.equals(Environment.MEDIA_MOUNTED)
9703 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
9704 }
9705
9706 if (!mounted) {
9707 return;
9708 }
9709
9710 final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009711 int[] users;
9712 if (userId == UserHandle.USER_ALL) {
9713 users = sUserManager.getUserIds();
9714 } else {
9715 users = new int[] { userId };
9716 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07009717 final ClearStorageConnection conn = new ClearStorageConnection();
Amith Yamasani27b89e62013-01-16 12:30:11 -08009718 if (mContext.bindServiceAsUser(
9719 containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
Jeff Sharkey752cd922012-09-23 16:25:12 -07009720 try {
9721 for (int curUser : users) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009722 long timeout = SystemClock.uptimeMillis() + 5000;
9723 synchronized (conn) {
9724 long now = SystemClock.uptimeMillis();
9725 while (conn.mContainerService == null && now < timeout) {
9726 try {
9727 conn.wait(timeout - now);
9728 } catch (InterruptedException e) {
9729 }
Dianne Hackborn183ce022012-06-29 15:00:21 -07009730 }
9731 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009732 if (conn.mContainerService == null) {
9733 return;
9734 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07009735
9736 final UserEnvironment userEnv = new UserEnvironment(curUser);
Jeff Sharkey1abdb712013-08-11 16:28:14 -07009737 clearDirectory(conn.mContainerService,
9738 userEnv.buildExternalStorageAppCacheDirs(packageName));
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009739 if (allData) {
Jeff Sharkey1abdb712013-08-11 16:28:14 -07009740 clearDirectory(conn.mContainerService,
9741 userEnv.buildExternalStorageAppDataDirs(packageName));
9742 clearDirectory(conn.mContainerService,
9743 userEnv.buildExternalStorageAppMediaDirs(packageName));
Dianne Hackborn183ce022012-06-29 15:00:21 -07009744 }
9745 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07009746 } finally {
9747 mContext.unbindService(conn);
Dianne Hackborn183ce022012-06-29 15:00:21 -07009748 }
9749 }
9750 }
9751
Amith Yamasani483f3b02012-03-13 16:08:00 -07009752 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 public void clearApplicationUserData(final String packageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07009754 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009755 mContext.enforceCallingOrSelfPermission(
9756 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
Amith Yamasanif203aee2012-08-29 18:41:53 -07009757 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "clear application data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 // Queue up an async operation since the package deletion may take a little while.
9759 mHandler.post(new Runnable() {
9760 public void run() {
9761 mHandler.removeCallbacks(this);
9762 final boolean succeeded;
9763 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07009764 succeeded = clearApplicationUserDataLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009766 clearExternalStorageDataSync(packageName, userId, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 if (succeeded) {
9768 // invoke DeviceStorageMonitor's update method to clear any notifications
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08009769 DeviceStorageMonitorInternal
9770 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009771 if (dsm != null) {
Adam Lesinskief2ea1f2013-12-05 16:48:06 -08009772 dsm.checkMemory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 }
9774 }
9775 if(observer != null) {
9776 try {
9777 observer.onRemoveCompleted(packageName, succeeded);
9778 } catch (RemoteException e) {
9779 Log.i(TAG, "Observer no longer exists.");
9780 }
9781 } //end if observer
9782 } //end run
9783 });
9784 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009785
Amith Yamasani483f3b02012-03-13 16:08:00 -07009786 private boolean clearApplicationUserDataLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009787 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009788 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 return false;
9790 }
9791 PackageParser.Package p;
9792 boolean dataOnly = false;
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009793 final int appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 synchronized (mPackages) {
9795 p = mPackages.get(packageName);
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009796 if (p == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 dataOnly = true;
9798 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009799 if ((ps == null) || (ps.pkg == null)) {
9800 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009801 return false;
9802 }
9803 p = ps.pkg;
9804 }
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009805 if (!dataOnly) {
9806 // need to check this only for fully installed applications
9807 if (p == null) {
9808 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
9809 return false;
9810 }
9811 final ApplicationInfo applicationInfo = p.applicationInfo;
9812 if (applicationInfo == null) {
9813 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
9814 return false;
9815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816 }
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009817 if (p != null && p.applicationInfo != null) {
9818 appId = p.applicationInfo.uid;
9819 } else {
9820 appId = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 }
9822 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07009823 int retCode = mInstaller.clearUserData(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009824 if (retCode < 0) {
9825 Slog.w(TAG, "Couldn't remove cache files for package: "
9826 + packageName);
9827 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 }
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009829 removeKeystoreDataIfNeeded(userId, appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 return true;
9831 }
9832
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009833 /**
9834 * Remove entries from the keystore daemon. Will only remove it if the
9835 * {@code appId} is valid.
9836 */
9837 private static void removeKeystoreDataIfNeeded(int userId, int appId) {
9838 if (appId < 0) {
9839 return;
9840 }
9841
9842 final KeyStore keyStore = KeyStore.getInstance();
9843 if (keyStore != null) {
9844 if (userId == UserHandle.USER_ALL) {
9845 for (final int individual : sUserManager.getUserIds()) {
9846 keyStore.clearUid(UserHandle.getUid(individual, appId));
9847 }
9848 } else {
9849 keyStore.clearUid(UserHandle.getUid(userId, appId));
9850 }
9851 } else {
9852 Slog.w(TAG, "Could not contact keystore to clear entries for app id " + appId);
9853 }
9854 }
9855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 public void deleteApplicationCacheFiles(final String packageName,
9857 final IPackageDataObserver observer) {
9858 mContext.enforceCallingOrSelfPermission(
9859 android.Manifest.permission.DELETE_CACHE_FILES, null);
9860 // Queue up an async operation since the package deletion may take a little while.
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07009861 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009862 mHandler.post(new Runnable() {
9863 public void run() {
9864 mHandler.removeCallbacks(this);
9865 final boolean succeded;
9866 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07009867 succeded = deleteApplicationCacheFilesLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009869 clearExternalStorageDataSync(packageName, userId, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009870 if(observer != null) {
9871 try {
9872 observer.onRemoveCompleted(packageName, succeded);
9873 } catch (RemoteException e) {
9874 Log.i(TAG, "Observer no longer exists.");
9875 }
9876 } //end if observer
9877 } //end run
9878 });
9879 }
9880
Amith Yamasani483f3b02012-03-13 16:08:00 -07009881 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009882 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009883 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 return false;
9885 }
9886 PackageParser.Package p;
9887 synchronized (mPackages) {
9888 p = mPackages.get(packageName);
9889 }
9890 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009891 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 return false;
9893 }
9894 final ApplicationInfo applicationInfo = p.applicationInfo;
9895 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009896 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 return false;
9898 }
Amith Yamasani54289b82012-10-01 10:39:14 -07009899 int retCode = mInstaller.deleteCacheFiles(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009900 if (retCode < 0) {
9901 Slog.w(TAG, "Couldn't remove cache files for package: "
Amith Yamasani54289b82012-10-01 10:39:14 -07009902 + packageName + " u" + userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009903 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009904 }
9905 return true;
9906 }
9907
Dianne Hackborn0c380492012-08-20 17:23:30 -07009908 public void getPackageSizeInfo(final String packageName, int userHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009909 final IPackageStatsObserver observer) {
9910 mContext.enforceCallingOrSelfPermission(
9911 android.Manifest.permission.GET_PACKAGE_SIZE, null);
Kenny Root366949c2011-01-14 17:18:14 -08009912
Dianne Hackborn0c380492012-08-20 17:23:30 -07009913 PackageStats stats = new PackageStats(packageName, userHandle);
Kenny Root366949c2011-01-14 17:18:14 -08009914
Kenny Roota69b7eb2012-05-14 14:47:06 -07009915 /*
9916 * Queue up an async operation since the package measurement may take a
9917 * little while.
9918 */
9919 Message msg = mHandler.obtainMessage(INIT_COPY);
9920 msg.obj = new MeasureParams(stats, observer);
9921 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 }
9923
Dianne Hackborn0c380492012-08-20 17:23:30 -07009924 private boolean getPackageSizeInfoLI(String packageName, int userHandle,
9925 PackageStats pStats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009927 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 return false;
9929 }
9930 PackageParser.Package p;
9931 boolean dataOnly = false;
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009932 String libDirPath = null;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07009933 String asecPath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009934 synchronized (mPackages) {
9935 p = mPackages.get(packageName);
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009936 PackageSetting ps = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009937 if(p == null) {
9938 dataOnly = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009940 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009941 return false;
9942 }
9943 p = ps.pkg;
9944 }
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009945 if (ps != null) {
9946 libDirPath = ps.nativeLibraryPathString;
9947 }
Kenny Root2afded12012-06-04 16:39:47 -07009948 if (p != null && (isExternal(p) || isForwardLocked(p))) {
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07009949 String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
9950 if (secureContainerId != null) {
9951 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
9952 }
9953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009954 }
9955 String publicSrcDir = null;
9956 if(!dataOnly) {
9957 final ApplicationInfo applicationInfo = p.applicationInfo;
9958 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009959 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009960 return false;
9961 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07009962 if (isForwardLocked(p)) {
9963 publicSrcDir = applicationInfo.publicSourceDir;
9964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 }
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009966 int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, libDirPath,
9967 publicSrcDir, asecPath, pStats);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009968 if (res < 0) {
9969 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 }
Kenny Root2afded12012-06-04 16:39:47 -07009971
9972 // Fix-up for forward-locked applications in ASEC containers.
9973 if (!isExternal(p)) {
9974 pStats.codeSize += pStats.externalCodeSize;
9975 pStats.externalCodeSize = 0L;
9976 }
9977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009978 return true;
9979 }
9980
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07009983 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 }
9985
9986 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07009987 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 }
9989
9990 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08009991 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 }
9993
Kenny Root447106f2011-03-23 11:00:15 -07009994 private int getUidTargetSdkVersionLockedLPr(int uid) {
9995 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009996 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07009997 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009998 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07009999 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010000 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -070010001 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010002 if (ps.pkg != null) {
10003 int v = ps.pkg.applicationInfo.targetSdkVersion;
10004 if (v < vers) vers = v;
10005 }
10006 }
10007 return vers;
10008 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -070010009 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010010 if (ps.pkg != null) {
10011 return ps.pkg.applicationInfo.targetSdkVersion;
10012 }
10013 }
10014 return Build.VERSION_CODES.CUR_DEVELOPMENT;
10015 }
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 public void addPreferredActivity(IntentFilter filter, int match,
Amith Yamasania3f133a2012-08-09 17:11:28 -070010018 ComponentName[] set, ComponentName activity, int userId) {
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010019 addPreferredActivityInternal(filter, match, set, activity, true, userId);
10020 }
10021
10022 private void addPreferredActivityInternal(IntentFilter filter, int match,
10023 ComponentName[] set, ComponentName activity, boolean always, int userId) {
Kenny Root447106f2011-03-23 11:00:15 -070010024 // writer
Amith Yamasania3f133a2012-08-09 17:11:28 -070010025 int callingUid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -070010026 enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
Christopher Tatee202cad2013-10-29 17:42:26 -070010027 if (filter.countActions() == 0) {
10028 Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
10029 return;
10030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010032 if (mContext.checkCallingOrSelfPermission(
10033 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
10034 != PackageManager.PERMISSION_GRANTED) {
Amith Yamasania3f133a2012-08-09 17:11:28 -070010035 if (getUidTargetSdkVersionLockedLPr(callingUid)
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010036 < Build.VERSION_CODES.FROYO) {
10037 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
Amith Yamasania3f133a2012-08-09 17:11:28 -070010038 + callingUid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010039 return;
10040 }
10041 mContext.enforceCallingOrSelfPermission(
10042 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10043 }
Amith Yamasania3f133a2012-08-09 17:11:28 -070010044
10045 Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010046 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
Dianne Hackborn63092712012-10-07 14:45:35 -070010047 mSettings.editPreferredActivitiesLPw(userId).addFilter(
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010048 new PreferredActivity(filter, match, set, activity, always));
Dianne Hackborn63092712012-10-07 14:45:35 -070010049 mSettings.writePackageRestrictionsLPr(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050 }
10051 }
10052
Satish Sampath8dbe6122009-06-02 23:35:54 +010010053 public void replacePreferredActivity(IntentFilter filter, int match,
10054 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +010010055 if (filter.countActions() != 1) {
10056 throw new IllegalArgumentException(
10057 "replacePreferredActivity expects filter to have only 1 action.");
10058 }
Satish Sampath8dbe6122009-06-02 23:35:54 +010010059 if (filter.countDataAuthorities() != 0
10060 || filter.countDataPaths() != 0
Christopher Tate087044c2013-11-11 17:43:43 -080010061 || filter.countDataSchemes() > 1
Satish Sampath8dbe6122009-06-02 23:35:54 +010010062 || filter.countDataTypes() != 0) {
10063 throw new IllegalArgumentException(
10064 "replacePreferredActivity expects filter to have no data authorities, " +
Christopher Tate087044c2013-11-11 17:43:43 -080010065 "paths, or types; and at most one scheme.");
Satish Sampath8dbe6122009-06-02 23:35:54 +010010066 }
10067 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010068 if (mContext.checkCallingOrSelfPermission(
10069 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
10070 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -070010071 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010072 < Build.VERSION_CODES.FROYO) {
10073 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
10074 + Binder.getCallingUid());
10075 return;
10076 }
10077 mContext.enforceCallingOrSelfPermission(
10078 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10079 }
Amith Yamasania3f133a2012-08-09 17:11:28 -070010080
10081 final int callingUserId = UserHandle.getCallingUserId();
Dianne Hackborn63092712012-10-07 14:45:35 -070010082 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(callingUserId);
10083 if (pir != null) {
Christopher Tate087044c2013-11-11 17:43:43 -080010084 Intent intent = new Intent(filter.getAction(0)).addCategory(filter.getCategory(0));
10085 if (filter.countDataSchemes() == 1) {
10086 Uri.Builder builder = new Uri.Builder();
10087 builder.scheme(filter.getDataScheme(0));
10088 intent.setData(builder.build());
Satish Sampath8dbe6122009-06-02 23:35:54 +010010089 }
Christopher Tate087044c2013-11-11 17:43:43 -080010090 List<PreferredActivity> matches = pir.queryIntent(
10091 intent, null, true, callingUserId);
10092 if (DEBUG_PREFERRED) {
10093 Slog.i(TAG, matches.size() + " preferred matches for " + intent);
10094 }
10095 for (int i = 0; i < matches.size(); i++) {
10096 PreferredActivity pa = matches.get(i);
10097 if (DEBUG_PREFERRED) {
10098 Slog.i(TAG, "Removing preferred activity "
10099 + pa.mPref.mComponent + ":");
10100 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
Dianne Hackborn63092712012-10-07 14:45:35 -070010101 }
Christopher Tate087044c2013-11-11 17:43:43 -080010102 pir.removeFilter(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -080010103 }
10104 }
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010105 addPreferredActivityInternal(filter, match, set, activity, true, callingUserId);
Satish Sampath8dbe6122009-06-02 23:35:54 +010010106 }
10107 }
10108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -070010110 final int uid = Binder.getCallingUid();
10111 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -080010113 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010114 if (pkg == null || pkg.applicationInfo.uid != uid) {
10115 if (mContext.checkCallingOrSelfPermission(
10116 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
10117 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -070010118 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010119 < Build.VERSION_CODES.FROYO) {
10120 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
10121 + Binder.getCallingUid());
10122 return;
10123 }
10124 mContext.enforceCallingOrSelfPermission(
10125 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10126 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -080010127 }
10128
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010129 int user = UserHandle.getCallingUserId();
10130 if (clearPackagePreferredActivitiesLPw(packageName, user)) {
10131 mSettings.writePackageRestrictionsLPr(user);
10132 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 }
10134 }
10135 }
10136
Amith Yamasania3f133a2012-08-09 17:11:28 -070010137 /** This method takes a specific user id as well as UserHandle.USER_ALL. */
10138 boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
Dianne Hackborn04505102012-02-29 12:34:04 -080010139 ArrayList<PreferredActivity> removed = null;
Dianne Hackborn63092712012-10-07 14:45:35 -070010140 boolean changed = false;
10141 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
10142 final int thisUserId = mSettings.mPreferredActivities.keyAt(i);
10143 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
10144 if (userId != UserHandle.USER_ALL && userId != thisUserId) {
Amith Yamasania3f133a2012-08-09 17:11:28 -070010145 continue;
10146 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010147 Iterator<PreferredActivity> it = pir.filterIterator();
10148 while (it.hasNext()) {
10149 PreferredActivity pa = it.next();
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010150 // Mark entry for removal only if it matches the package name
10151 // and the entry is of type "always".
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010152 if (packageName == null ||
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010153 (pa.mPref.mComponent.getPackageName().equals(packageName)
10154 && pa.mPref.mAlways)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010155 if (removed == null) {
10156 removed = new ArrayList<PreferredActivity>();
10157 }
10158 removed.add(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -080010159 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010160 }
10161 if (removed != null) {
10162 for (int j=0; j<removed.size(); j++) {
10163 PreferredActivity pa = removed.get(j);
10164 pir.removeFilter(pa);
10165 }
10166 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 }
10168 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010169 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 }
10171
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010172 public void resetPreferredActivities(int userId) {
10173 mContext.enforceCallingOrSelfPermission(
10174 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10175 // writer
10176 synchronized (mPackages) {
10177 int user = UserHandle.getCallingUserId();
10178 clearPackagePreferredActivitiesLPw(null, user);
10179 mSettings.readDefaultPreferredAppsLPw(this, user);
10180 mSettings.writePackageRestrictionsLPr(user);
10181 scheduleWriteSettingsLocked();
10182 }
10183 }
10184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010185 public int getPreferredActivities(List<IntentFilter> outFilters,
10186 List<ComponentName> outActivities, String packageName) {
10187
10188 int num = 0;
Amith Yamasania3f133a2012-08-09 17:11:28 -070010189 final int userId = UserHandle.getCallingUserId();
Kenny Root447106f2011-03-23 11:00:15 -070010190 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 synchronized (mPackages) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010192 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
10193 if (pir != null) {
10194 final Iterator<PreferredActivity> it = pir.filterIterator();
10195 while (it.hasNext()) {
10196 final PreferredActivity pa = it.next();
10197 if (packageName == null
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010198 || (pa.mPref.mComponent.getPackageName().equals(packageName)
10199 && pa.mPref.mAlways)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010200 if (outFilters != null) {
10201 outFilters.add(new IntentFilter(pa));
10202 }
10203 if (outActivities != null) {
10204 outActivities.add(pa.mPref.mComponent);
10205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 }
10207 }
10208 }
10209 }
10210
10211 return num;
10212 }
10213
Amith Yamasani483f3b02012-03-13 16:08:00 -070010214 @Override
Christopher Tatea2a0850d2013-09-05 16:38:58 -070010215 public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
10216 Intent intent = new Intent(Intent.ACTION_MAIN);
10217 intent.addCategory(Intent.CATEGORY_HOME);
10218
10219 final int callingUserId = UserHandle.getCallingUserId();
Christopher Tatebd413f62013-09-18 18:31:59 -070010220 List<ResolveInfo> list = queryIntentActivities(intent, null,
10221 PackageManager.GET_META_DATA, callingUserId);
Christopher Tatea2a0850d2013-09-05 16:38:58 -070010222 ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
Dianne Hackborn38ba6e92013-09-23 11:08:52 -070010223 true, false, false, callingUserId);
Christopher Tatea2a0850d2013-09-05 16:38:58 -070010224
10225 allHomeCandidates.clear();
10226 if (list != null) {
10227 for (ResolveInfo ri : list) {
10228 allHomeCandidates.add(ri);
10229 }
10230 }
10231 return (preferred == null || preferred.activityInfo == null)
10232 ? null
10233 : new ComponentName(preferred.activityInfo.packageName,
10234 preferred.activityInfo.name);
10235 }
10236
10237 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 public void setApplicationEnabledSetting(String appPackageName,
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010239 int newState, int flags, int userId, String callingPackage) {
Amith Yamasani13593602012-03-22 16:16:17 -070010240 if (!sUserManager.exists(userId)) return;
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010241 if (callingPackage == null) {
10242 callingPackage = Integer.toString(Binder.getCallingUid());
10243 }
10244 setEnabledSetting(appPackageName, null, newState, flags, userId, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 }
10246
Amith Yamasani483f3b02012-03-13 16:08:00 -070010247 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248 public void setComponentEnabledSetting(ComponentName componentName,
Amith Yamasani483f3b02012-03-13 16:08:00 -070010249 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010250 if (!sUserManager.exists(userId)) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 setEnabledSetting(componentName.getPackageName(),
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010252 componentName.getClassName(), newState, flags, userId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 }
10254
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010255 private void setEnabledSetting(final String packageName, String className, int newState,
10256 final int flags, int userId, String callingPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010257 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
10258 || newState == COMPONENT_ENABLED_STATE_ENABLED
Dianne Hackborn0ac30312011-06-17 14:49:23 -070010259 || newState == COMPONENT_ENABLED_STATE_DISABLED
Dianne Hackbornfd7aded2013-01-22 17:10:23 -080010260 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER
10261 || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 throw new IllegalArgumentException("Invalid new component state: "
10263 + newState);
10264 }
10265 PackageSetting pkgSetting;
10266 final int uid = Binder.getCallingUid();
Dianne Hackbornfd7aded2013-01-22 17:10:23 -080010267 final int permission = mContext.checkCallingOrSelfPermission(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
Amith Yamasanif203aee2012-08-29 18:41:53 -070010269 enforceCrossUserPermission(uid, userId, false, "set enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010270 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010271 boolean sendNow = false;
10272 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010273 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010275 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -070010276
10277 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010278 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010279 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010281 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010283 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010286 "Unknown component: " + packageName
10287 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288 }
Amith Yamasani483f3b02012-03-13 16:08:00 -070010289 // Allow root and verify that userId is not being specified by a different user
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070010290 if (!allowedByPermission && !UserHandle.isSameApp(uid, pkgSetting.appId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 throw new SecurityException(
10292 "Permission Denial: attempt to change component state from pid="
10293 + Binder.getCallingPid()
Amith Yamasani13593602012-03-22 16:16:17 -070010294 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010296 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 // We're dealing with an application/package level state change
Amith Yamasani483f3b02012-03-13 16:08:00 -070010298 if (pkgSetting.getEnabled(userId) == newState) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010299 // Nothing to do
10300 return;
10301 }
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010302 if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
10303 || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
10304 // Don't care about who enables an app.
10305 callingPackage = null;
10306 }
10307 pkgSetting.setEnabled(newState, userId, callingPackage);
Amith Yamasani13593602012-03-22 16:16:17 -070010308 // pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 } else {
10310 // We're dealing with a component level state change
Dianne Hackborn65696252012-03-05 18:49:21 -080010311 // First, verify that this is a valid class name.
10312 PackageParser.Package pkg = pkgSetting.pkg;
10313 if (pkg == null || !pkg.hasComponentClassName(className)) {
10314 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
10315 throw new IllegalArgumentException("Component class " + className
10316 + " does not exist in " + packageName);
10317 } else {
10318 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
10319 + className + " does not exist in " + packageName);
10320 }
10321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 switch (newState) {
10323 case COMPONENT_ENABLED_STATE_ENABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -070010324 if (!pkgSetting.enableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010325 return;
10326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 break;
10328 case COMPONENT_ENABLED_STATE_DISABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -070010329 if (!pkgSetting.disableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010330 return;
10331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 break;
10333 case COMPONENT_ENABLED_STATE_DEFAULT:
Amith Yamasani483f3b02012-03-13 16:08:00 -070010334 if (!pkgSetting.restoreComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010335 return;
10336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010337 break;
10338 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010339 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010340 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 }
10342 }
Amith Yamasani483f3b02012-03-13 16:08:00 -070010343 mSettings.writePackageRestrictionsLPr(userId);
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010344 components = mPendingBroadcasts.get(userId, packageName);
Kenny Root447106f2011-03-23 11:00:15 -070010345 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010346 if (newPackage) {
10347 components = new ArrayList<String>();
10348 }
10349 if (!components.contains(componentName)) {
10350 components.add(componentName);
10351 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010352 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
10353 sendNow = true;
10354 // Purge entry from pending broadcast list if another one exists already
10355 // since we are sending one right away.
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010356 mPendingBroadcasts.remove(userId, packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010357 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010358 if (newPackage) {
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010359 mPendingBroadcasts.put(userId, packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010360 }
10361 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
10362 // Schedule a message
10363 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
10364 }
10365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010366 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 long callingId = Binder.clearCallingIdentity();
10369 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010370 if (sendNow) {
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010371 packageUid = UserHandle.getUid(userId, pkgSetting.appId);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010372 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010373 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 } finally {
10376 Binder.restoreCallingIdentity(callingId);
10377 }
10378 }
10379
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010380 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010381 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -080010382 if (DEBUG_INSTALL)
10383 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
10384 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010385 Bundle extras = new Bundle(4);
10386 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
10387 String nameList[] = new String[componentNames.size()];
10388 componentNames.toArray(nameList);
10389 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010390 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
10391 extras.putInt(Intent.EXTRA_UID, packageUid);
Amith Yamasani13593602012-03-22 16:16:17 -070010392 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -070010393 new int[] {UserHandle.getUserId(packageUid)});
Dianne Hackborne7f97212011-02-24 14:40:20 -080010394 }
10395
Amith Yamasani483f3b02012-03-13 16:08:00 -070010396 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010397 if (!sUserManager.exists(userId)) return;
Dianne Hackborne7f97212011-02-24 14:40:20 -080010398 final int uid = Binder.getCallingUid();
10399 final int permission = mContext.checkCallingOrSelfPermission(
10400 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
10401 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Amith Yamasanif203aee2012-08-29 18:41:53 -070010402 enforceCrossUserPermission(uid, userId, true, "stop package");
Kenny Root447106f2011-03-23 11:00:15 -070010403 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -080010404 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -070010405 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
Amith Yamasani483f3b02012-03-13 16:08:00 -070010406 uid, userId)) {
10407 scheduleWritePackageRestrictionsLocked(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010408 }
10409 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010410 }
10411
Jacek Surazski65e13172009-04-28 15:26:38 +020010412 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -070010413 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +020010414 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -070010415 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +020010416 }
10417 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010418
Amith Yamasani483f3b02012-03-13 16:08:00 -070010419 @Override
10420 public int getApplicationEnabledSetting(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010421 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -070010422 int uid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -070010423 enforceCrossUserPermission(uid, userId, false, "get enabled");
Kenny Root447106f2011-03-23 11:00:15 -070010424 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -070010426 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 }
10428 }
10429
Amith Yamasani483f3b02012-03-13 16:08:00 -070010430 @Override
10431 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010432 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -070010433 int uid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -070010434 enforceCrossUserPermission(uid, userId, false, "get component enabled");
Kenny Root447106f2011-03-23 11:00:15 -070010435 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -070010437 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010438 }
10439 }
10440
10441 public void enterSafeMode() {
Kenny Root461ff1f2011-08-09 09:43:03 -070010442 enforceSystemOrRoot("Only the system can request entering safe mode");
10443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010444 if (!mSystemReady) {
10445 mSafeMode = true;
10446 }
10447 }
10448
10449 public void systemReady() {
10450 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010451
10452 // Read the compatibilty setting when the system is ready.
Jeff Sharkey6e2bee72012-10-01 13:39:08 -070010453 boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010454 mContext.getContentResolver(),
Jeff Sharkey6e2bee72012-10-01 13:39:08 -070010455 android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -070010456 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010457 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -070010458 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010459 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010460
10461 synchronized (mPackages) {
10462 // Verify that all of the preferred activity components actually
10463 // exist. It is possible for applications to be updated and at
10464 // that point remove a previously declared activity component that
10465 // had been set as a preferred activity. We try to clean this up
10466 // the next time we encounter that preferred activity, but it is
10467 // possible for the user flow to never be able to return to that
10468 // situation so here we do a sanity check to make sure we haven't
10469 // left any junk around.
10470 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
10471 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
10472 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
10473 removed.clear();
10474 for (PreferredActivity pa : pir.filterSet()) {
10475 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
10476 removed.add(pa);
10477 }
10478 }
10479 if (removed.size() > 0) {
10480 for (int j=0; j<removed.size(); j++) {
10481 PreferredActivity pa = removed.get(i);
Dianne Hackborn63092712012-10-07 14:45:35 -070010482 Slog.w(TAG, "Removing dangling preferred activity: "
Dianne Hackborn40e9f292012-11-27 19:12:23 -080010483 + pa.mPref.mComponent);
Dianne Hackborn63092712012-10-07 14:45:35 -070010484 pir.removeFilter(pa);
10485 }
10486 mSettings.writePackageRestrictionsLPr(
10487 mSettings.mPreferredActivities.keyAt(i));
10488 }
10489 }
10490 }
Amith Yamasani1a7472e2013-07-02 11:17:30 -070010491 sUserManager.systemReady();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 }
10493
10494 public boolean isSafeMode() {
10495 return mSafeMode;
10496 }
10497
10498 public boolean hasSystemUidErrors() {
10499 return mHasSystemUidErrors;
10500 }
10501
10502 static String arrayToString(int[] array) {
10503 StringBuffer buf = new StringBuffer(128);
10504 buf.append('[');
10505 if (array != null) {
10506 for (int i=0; i<array.length; i++) {
10507 if (i > 0) buf.append(", ");
10508 buf.append(array[i]);
10509 }
10510 }
10511 buf.append(']');
10512 return buf.toString();
10513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010514
Kenny Root447106f2011-03-23 11:00:15 -070010515 static class DumpState {
10516 public static final int DUMP_LIBS = 1 << 0;
10517
10518 public static final int DUMP_FEATURES = 1 << 1;
10519
10520 public static final int DUMP_RESOLVERS = 1 << 2;
10521
10522 public static final int DUMP_PERMISSIONS = 1 << 3;
10523
10524 public static final int DUMP_PACKAGES = 1 << 4;
10525
10526 public static final int DUMP_SHARED_USERS = 1 << 5;
10527
10528 public static final int DUMP_MESSAGES = 1 << 6;
10529
10530 public static final int DUMP_PROVIDERS = 1 << 7;
10531
Kenny Root05ca4c92011-09-15 10:36:25 -070010532 public static final int DUMP_VERIFIERS = 1 << 8;
10533
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010534 public static final int DUMP_PREFERRED = 1 << 9;
10535
10536 public static final int DUMP_PREFERRED_XML = 1 << 10;
10537
Geremy Condraf1bcca82013-01-07 22:35:24 -080010538 public static final int DUMP_KEYSETS = 1 << 11;
10539
Kenny Root447106f2011-03-23 11:00:15 -070010540 public static final int OPTION_SHOW_FILTERS = 1 << 0;
10541
10542 private int mTypes;
10543
10544 private int mOptions;
10545
10546 private boolean mTitlePrinted;
10547
10548 private SharedUserSetting mSharedUser;
10549
10550 public boolean isDumping(int type) {
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010551 if (mTypes == 0 && type != DUMP_PREFERRED_XML) {
Kenny Root447106f2011-03-23 11:00:15 -070010552 return true;
10553 }
10554
10555 return (mTypes & type) != 0;
10556 }
10557
10558 public void setDump(int type) {
10559 mTypes |= type;
10560 }
10561
10562 public boolean isOptionEnabled(int option) {
10563 return (mOptions & option) != 0;
10564 }
10565
10566 public void setOptionEnabled(int option) {
10567 mOptions |= option;
10568 }
10569
10570 public boolean onTitlePrinted() {
10571 final boolean printed = mTitlePrinted;
10572 mTitlePrinted = true;
10573 return printed;
10574 }
10575
10576 public boolean getTitlePrinted() {
10577 return mTitlePrinted;
10578 }
10579
10580 public void setTitlePrinted(boolean enabled) {
10581 mTitlePrinted = enabled;
10582 }
10583
10584 public SharedUserSetting getSharedUser() {
10585 return mSharedUser;
10586 }
10587
10588 public void setSharedUser(SharedUserSetting user) {
10589 mSharedUser = user;
10590 }
10591 }
10592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 @Override
10594 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10595 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
10596 != PackageManager.PERMISSION_GRANTED) {
10597 pw.println("Permission Denial: can't dump ActivityManager from from pid="
10598 + Binder.getCallingPid()
10599 + ", uid=" + Binder.getCallingUid()
10600 + " without permission "
10601 + android.Manifest.permission.DUMP);
10602 return;
10603 }
10604
Kenny Root447106f2011-03-23 11:00:15 -070010605 DumpState dumpState = new DumpState();
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010606 boolean fullPreferred = false;
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010607 boolean checkin = false;
10608
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010609 String packageName = null;
10610
10611 int opti = 0;
10612 while (opti < args.length) {
10613 String opt = args[opti];
10614 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10615 break;
10616 }
10617 opti++;
10618 if ("-a".equals(opt)) {
10619 // Right now we only know how to print all.
10620 } else if ("-h".equals(opt)) {
10621 pw.println("Package manager dump options:");
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010622 pw.println(" [-h] [-f] [--checkin] [cmd] ...");
10623 pw.println(" --checkin: dump for a checkin");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010624 pw.println(" -f: print details of intent filters");
10625 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010626 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010627 pw.println(" l[ibraries]: list known shared libraries");
10628 pw.println(" f[ibraries]: list device features");
10629 pw.println(" r[esolvers]: dump intent resolvers");
10630 pw.println(" perm[issions]: dump permissions");
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010631 pw.println(" pref[erred]: print preferred package settings");
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010632 pw.println(" preferred-xml [--full]: print preferred package settings as xml");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010633 pw.println(" prov[iders]: dump content providers");
10634 pw.println(" p[ackages]: dump installed packages");
10635 pw.println(" s[hared-users]: dump shared user IDs");
10636 pw.println(" m[essages]: print collected runtime messages");
Kenny Root05ca4c92011-09-15 10:36:25 -070010637 pw.println(" v[erifiers]: print package verifier info");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010638 pw.println(" <package.name>: info about given package");
Geremy Condraf1bcca82013-01-07 22:35:24 -080010639 pw.println(" k[eysets]: print known keysets");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010640 return;
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010641 } else if ("--checkin".equals(opt)) {
10642 checkin = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010643 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -070010644 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010645 } else {
10646 pw.println("Unknown argument: " + opt + "; use -h for help");
10647 }
10648 }
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010649
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010650 // Is the caller requesting to dump a particular piece of data?
10651 if (opti < args.length) {
10652 String cmd = args[opti];
10653 opti++;
10654 // Is this a package name?
10655 if ("android".equals(cmd) || cmd.contains(".")) {
10656 packageName = cmd;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010657 // When dumping a single package, we always dump all of its
10658 // filter information since the amount of data will be reasonable.
10659 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010660 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010661 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010662 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010663 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010664 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010665 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010666 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010667 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010668 } else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
10669 dumpState.setDump(DumpState.DUMP_PREFERRED);
10670 } else if ("preferred-xml".equals(cmd)) {
10671 dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010672 if (opti < args.length && "--full".equals(args[opti])) {
10673 fullPreferred = true;
Dianne Hackbornd4d93642013-01-29 16:12:48 -080010674 opti++;
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010675 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010676 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010677 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010678 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010679 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010680 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010681 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010682 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010683 dumpState.setDump(DumpState.DUMP_MESSAGES);
Kenny Root05ca4c92011-09-15 10:36:25 -070010684 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
10685 dumpState.setDump(DumpState.DUMP_VERIFIERS);
Geremy Condraf1bcca82013-01-07 22:35:24 -080010686 } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
10687 dumpState.setDump(DumpState.DUMP_KEYSETS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010688 }
10689 }
Kenny Root447106f2011-03-23 11:00:15 -070010690
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010691 if (checkin) {
10692 pw.println("vers,1");
10693 }
10694
Kenny Root447106f2011-03-23 11:00:15 -070010695 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 synchronized (mPackages) {
Kenny Root05ca4c92011-09-15 10:36:25 -070010697 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010698 if (!checkin) {
10699 if (dumpState.onTitlePrinted())
10700 pw.println();
10701 pw.println("Verifiers:");
10702 pw.print(" Required: ");
10703 pw.print(mRequiredVerifierPackage);
10704 pw.print(" (uid=");
10705 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
10706 pw.println(")");
10707 } else if (mRequiredVerifierPackage != null) {
10708 pw.print("vrfy,"); pw.print(mRequiredVerifierPackage);
10709 pw.print(","); pw.println(getPackageUid(mRequiredVerifierPackage, 0));
10710 }
Kenny Root05ca4c92011-09-15 10:36:25 -070010711 }
10712
Kenny Root447106f2011-03-23 11:00:15 -070010713 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010714 boolean printedHeader = false;
Kenny Root447106f2011-03-23 11:00:15 -070010715 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010716 while (it.hasNext()) {
10717 String name = it.next();
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010718 SharedLibraryEntry ent = mSharedLibraries.get(name);
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010719 if (!checkin) {
10720 if (!printedHeader) {
10721 if (dumpState.onTitlePrinted())
10722 pw.println();
10723 pw.println("Libraries:");
10724 printedHeader = true;
10725 }
10726 pw.print(" ");
Dianne Hackbornc895be72013-03-11 17:48:43 -070010727 } else {
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010728 pw.print("lib,");
10729 }
10730 pw.print(name);
10731 if (!checkin) {
10732 pw.print(" -> ");
10733 }
10734 if (ent.path != null) {
10735 if (!checkin) {
10736 pw.print("(jar) ");
10737 pw.print(ent.path);
10738 } else {
10739 pw.print(",jar,");
10740 pw.print(ent.path);
10741 }
10742 } else {
10743 if (!checkin) {
10744 pw.print("(apk) ");
10745 pw.print(ent.apk);
10746 } else {
10747 pw.print(",apk,");
10748 pw.print(ent.apk);
10749 }
Dianne Hackbornc895be72013-03-11 17:48:43 -070010750 }
10751 pw.println();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010752 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010753 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010754
Kenny Root447106f2011-03-23 11:00:15 -070010755 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
10756 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010757 pw.println();
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010758 if (!checkin) {
10759 pw.println("Features:");
10760 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010761 Iterator<String> it = mAvailableFeatures.keySet().iterator();
10762 while (it.hasNext()) {
10763 String name = it.next();
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010764 if (!checkin) {
10765 pw.print(" ");
10766 } else {
10767 pw.print("feat,");
10768 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010769 pw.println(name);
10770 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010771 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010772
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010773 if (!checkin && dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
Kenny Root447106f2011-03-23 11:00:15 -070010774 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
10775 : "Activity Resolver Table:", " ", packageName,
10776 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10777 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010778 }
Kenny Root447106f2011-03-23 11:00:15 -070010779 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
10780 : "Receiver Resolver Table:", " ", packageName,
10781 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10782 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010783 }
Kenny Root447106f2011-03-23 11:00:15 -070010784 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
10785 : "Service Resolver Table:", " ", packageName,
10786 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10787 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010788 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -070010789 if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
10790 : "Provider Resolver Table:", " ", packageName,
10791 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10792 dumpState.setTitlePrinted(true);
10793 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010794 }
10795
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010796 if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010797 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
10798 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
10799 int user = mSettings.mPreferredActivities.keyAt(i);
10800 if (pir.dump(pw,
10801 dumpState.getTitlePrinted()
10802 ? "\nPreferred Activities User " + user + ":"
10803 : "Preferred Activities User " + user + ":", " ",
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070010804 packageName, true)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010805 dumpState.setTitlePrinted(true);
10806 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010807 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010808 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010809
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010810 if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010811 pw.flush();
10812 FileOutputStream fout = new FileOutputStream(fd);
10813 BufferedOutputStream str = new BufferedOutputStream(fout);
10814 XmlSerializer serializer = new FastXmlSerializer();
10815 try {
10816 serializer.setOutput(str, "utf-8");
10817 serializer.startDocument(null, true);
10818 serializer.setFeature(
10819 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010820 mSettings.writePreferredActivitiesLPr(serializer, 0, fullPreferred);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010821 serializer.endDocument();
10822 serializer.flush();
10823 } catch (IllegalArgumentException e) {
10824 pw.println("Failed writing: " + e);
10825 } catch (IllegalStateException e) {
10826 pw.println("Failed writing: " + e);
10827 } catch (IOException e) {
10828 pw.println("Failed writing: " + e);
10829 }
10830 }
10831
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010832 if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
Kenny Root447106f2011-03-23 11:00:15 -070010833 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010835
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010836 if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
Kenny Root447106f2011-03-23 11:00:15 -070010837 boolean printedSomething = false;
Jeff Sharkey85f5f812013-10-07 10:16:12 -070010838 for (PackageParser.Provider p : mProviders.mProviders.values()) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010839 if (packageName != null && !packageName.equals(p.info.packageName)) {
10840 continue;
10841 }
10842 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -070010843 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010844 pw.println();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010845 pw.println("Registered ContentProviders:");
10846 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010847 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070010848 pw.print(" "); p.printComponentShortName(pw); pw.println(":");
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010849 pw.print(" "); pw.println(p.toString());
10850 }
10851 printedSomething = false;
Jeff Sharkey85f5f812013-10-07 10:16:12 -070010852 for (Map.Entry<String, PackageParser.Provider> entry :
10853 mProvidersByAuthority.entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010854 PackageParser.Provider p = entry.getValue();
10855 if (packageName != null && !packageName.equals(p.info.packageName)) {
10856 continue;
10857 }
10858 if (!printedSomething) {
10859 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010860 pw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010861 pw.println("ContentProvider Authorities:");
10862 printedSomething = true;
10863 }
10864 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
10865 pw.print(" "); pw.println(p.toString());
Kenny Rooteca64b32012-06-25 16:37:32 -070010866 if (p.info != null && p.info.applicationInfo != null) {
10867 final String appInfo = p.info.applicationInfo.toString();
10868 pw.print(" applicationInfo="); pw.println(appInfo);
10869 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010870 }
10871 }
Geremy Condraf1bcca82013-01-07 22:35:24 -080010872
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010873 if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010874 mSettings.mKeySetManager.dump(pw, packageName, dumpState);
Geremy Condraf1bcca82013-01-07 22:35:24 -080010875 }
10876
Kenny Root447106f2011-03-23 11:00:15 -070010877 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010878 mSettings.dumpPackagesLPr(pw, packageName, dumpState, checkin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 }
Kenny Root447106f2011-03-23 11:00:15 -070010880
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010881 if (!checkin && dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
Kenny Root447106f2011-03-23 11:00:15 -070010882 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -080010883 }
Kenny Root447106f2011-03-23 11:00:15 -070010884
Dianne Hackborn60dc0d92014-01-17 13:29:21 -080010885 if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
Kenny Root447106f2011-03-23 11:00:15 -070010886 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010887 pw.println();
Kenny Root447106f2011-03-23 11:00:15 -070010888 mSettings.dumpReadMessagesLPr(pw, dumpState);
10889
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010890 pw.println();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010891 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -070010892 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -080010893 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010894 try {
10895 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -070010896 final int avail = in.available();
10897 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010898 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010899 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010900 } catch (FileNotFoundException e) {
10901 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -080010902 } finally {
10903 if (in != null) {
10904 try {
10905 in.close();
Kenny Root447106f2011-03-23 11:00:15 -070010906 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -080010907 }
10908 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010909 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -080010910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 }
10912 }
10913
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010914 // ------- apps on sdcard specific code -------
10915 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -070010916
Kenny Root305bcbf2010-09-03 07:56:38 -070010917 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -070010918
Kenny Root305bcbf2010-09-03 07:56:38 -070010919 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -070010920
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080010921 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010922
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010923 private String getEncryptKey() {
10924 try {
Kenny Root305bcbf2010-09-03 07:56:38 -070010925 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
10926 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010927 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -070010928 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
10929 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010930 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010931 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010932 return null;
10933 }
10934 }
10935 return sdEncKey;
10936 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010937 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010938 return null;
Rich Cannings8d578832010-09-09 15:12:40 -070010939 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -070010940 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -070010941 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010942 }
Rich Cannings8d578832010-09-09 15:12:40 -070010943
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010944 }
10945
Kenny Root447106f2011-03-23 11:00:15 -070010946 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -070010947 int tmpIdx = 1;
10948 String list[] = PackageHelper.getSecureContainerList();
10949 if (list != null) {
10950 for (final String name : list) {
10951 // Ignore null and non-temporary container entries
10952 if (name == null || !name.startsWith(mTempContainerPrefix)) {
10953 continue;
10954 }
10955
10956 String subStr = name.substring(mTempContainerPrefix.length());
10957 try {
10958 int cid = Integer.parseInt(subStr);
10959 if (cid >= tmpIdx) {
10960 tmpIdx = cid + 1;
10961 }
10962 } catch (NumberFormatException e) {
10963 }
10964 }
10965 }
10966 return mTempContainerPrefix + tmpIdx;
10967 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010968
Kenny Root447106f2011-03-23 11:00:15 -070010969 /*
10970 * Update media status on PackageManager.
10971 */
10972 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
10973 int callingUid = Binder.getCallingUid();
10974 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
10975 throw new SecurityException("Media status can only be updated by the system");
10976 }
10977 // reader; this apparently protects mMediaMounted, but should probably
10978 // be a different lock in that case.
10979 synchronized (mPackages) {
10980 Log.i(TAG, "Updating external media status from "
10981 + (mMediaMounted ? "mounted" : "unmounted") + " to "
10982 + (mediaStatus ? "mounted" : "unmounted"));
10983 if (DEBUG_SD_INSTALL)
10984 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
10985 + ", mMediaMounted=" + mMediaMounted);
10986 if (mediaStatus == mMediaMounted) {
10987 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
10988 : 0, -1);
10989 mHandler.sendMessage(msg);
10990 return;
10991 }
10992 mMediaMounted = mediaStatus;
10993 }
10994 // Queue up an async operation since the package installation may take a
10995 // little while.
10996 mHandler.post(new Runnable() {
10997 public void run() {
Kenny Root438a0ef2012-08-09 13:36:16 -070010998 updateExternalMediaStatusInner(mediaStatus, reportStatus, true);
Kenny Root447106f2011-03-23 11:00:15 -070010999 }
11000 });
11001 }
11002
Kenny Root51a573c2012-05-17 13:30:28 -070011003 /**
11004 * Called by MountService when the initial ASECs to scan are available.
11005 * Should block until all the ASEC containers are finished being scanned.
11006 */
11007 public void scanAvailableAsecs() {
Kenny Root438a0ef2012-08-09 13:36:16 -070011008 updateExternalMediaStatusInner(true, false, false);
Kenny Root51a573c2012-05-17 13:30:28 -070011009 }
11010
Kenny Root447106f2011-03-23 11:00:15 -070011011 /*
11012 * Collect information of applications on external media, map them against
11013 * existing containers and update information based on current mount status.
11014 * Please note that we always have to report status if reportStatus has been
11015 * set to true especially when unloading packages.
11016 */
Kenny Root438a0ef2012-08-09 13:36:16 -070011017 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus,
11018 boolean externalStorage) {
Kenny Root447106f2011-03-23 11:00:15 -070011019 // Collection of uids
11020 int uidArr[] = null;
11021 // Collection of stale containers
11022 HashSet<String> removeCids = new HashSet<String>();
11023 // Collection of packages on external media with valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -070011024 HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
Kenny Root447106f2011-03-23 11:00:15 -070011025 // Get list of secure containers.
11026 final String list[] = PackageHelper.getSecureContainerList();
11027 if (list == null || list.length == 0) {
11028 Log.i(TAG, "No secure containers on sdcard");
11029 } else {
11030 // Process list of secure containers and categorize them
11031 // as active or stale based on their package internal state.
11032 int uidList[] = new int[list.length];
11033 int num = 0;
11034 // reader
11035 synchronized (mPackages) {
11036 for (String cid : list) {
Kenny Root447106f2011-03-23 11:00:15 -070011037 if (DEBUG_SD_INSTALL)
11038 Log.i(TAG, "Processing container " + cid);
Kenny Rootc7a89992012-06-05 15:13:17 -070011039 String pkgName = getAsecPackageName(cid);
Kenny Root447106f2011-03-23 11:00:15 -070011040 if (pkgName == null) {
11041 if (DEBUG_SD_INSTALL)
11042 Log.i(TAG, "Container : " + cid + " stale");
11043 removeCids.add(cid);
11044 continue;
11045 }
11046 if (DEBUG_SD_INSTALL)
11047 Log.i(TAG, "Looking for pkg : " + pkgName);
Kenny Rootc7a89992012-06-05 15:13:17 -070011048
11049 final PackageSetting ps = mSettings.mPackages.get(pkgName);
11050 if (ps == null) {
11051 Log.i(TAG, "Deleting container with no matching settings " + cid);
11052 removeCids.add(cid);
11053 continue;
11054 }
11055
Kenny Root438a0ef2012-08-09 13:36:16 -070011056 /*
11057 * Skip packages that are not external if we're unmounting
11058 * external storage.
11059 */
11060 if (externalStorage && !isMounted && !isExternal(ps)) {
11061 continue;
11062 }
11063
Kenny Rootc7a89992012-06-05 15:13:17 -070011064 final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
Kenny Root447106f2011-03-23 11:00:15 -070011065 // The package status is changed only if the code path
11066 // matches between settings and the container id.
Kenny Rootc7a89992012-06-05 15:13:17 -070011067 if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
11068 if (DEBUG_SD_INSTALL) {
Kenny Root447106f2011-03-23 11:00:15 -070011069 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
11070 + " at code path: " + ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -070011071 }
11072
Kenny Root447106f2011-03-23 11:00:15 -070011073 // We do have a valid package installed on sdcard
11074 processCids.put(args, ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -070011075 final int uid = ps.appId;
Kenny Root447106f2011-03-23 11:00:15 -070011076 if (uid != -1) {
11077 uidList[num++] = uid;
11078 }
11079 } else {
Kenny Rootc7a89992012-06-05 15:13:17 -070011080 Log.i(TAG, "Deleting stale container for " + cid);
Kenny Root447106f2011-03-23 11:00:15 -070011081 removeCids.add(cid);
11082 }
11083 }
11084 }
11085
11086 if (num > 0) {
11087 // Sort uid list
11088 Arrays.sort(uidList, 0, num);
11089 // Throw away duplicates
11090 uidArr = new int[num];
11091 uidArr[0] = uidList[0];
11092 int di = 0;
11093 for (int i = 1; i < num; i++) {
11094 if (uidList[i - 1] != uidList[i]) {
11095 uidArr[di++] = uidList[i];
11096 }
11097 }
11098 }
11099 }
11100 // Process packages with valid entries.
Kenny Root6dceb882012-04-12 14:23:49 -070011101 if (isMounted) {
Kenny Root447106f2011-03-23 11:00:15 -070011102 if (DEBUG_SD_INSTALL)
11103 Log.i(TAG, "Loading packages");
11104 loadMediaPackages(processCids, uidArr, removeCids);
Jeff Sharkey752cd922012-09-23 16:25:12 -070011105 startCleaningPackages();
Kenny Root447106f2011-03-23 11:00:15 -070011106 } else {
11107 if (DEBUG_SD_INSTALL)
11108 Log.i(TAG, "Unloading packages");
11109 unloadMediaPackages(processCids, uidArr, reportStatus);
11110 }
11111 }
11112
Christopher Tated15967482013-10-04 13:57:22 -070011113 private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
11114 ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
Kenny Root447106f2011-03-23 11:00:15 -070011115 int size = pkgList.size();
11116 if (size > 0) {
11117 // Send broadcasts here
11118 Bundle extras = new Bundle();
11119 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
11120 .toArray(new String[size]));
11121 if (uidArr != null) {
11122 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
11123 }
Christopher Tate8b3e3ec2014-01-08 16:54:25 -080011124 if (replacing) {
Christopher Tated15967482013-10-04 13:57:22 -070011125 extras.putBoolean(Intent.EXTRA_REPLACING, replacing);
11126 }
Kenny Root447106f2011-03-23 11:00:15 -070011127 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
11128 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Dianne Hackborn7767eac2012-08-23 18:25:40 -070011129 sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
Kenny Root447106f2011-03-23 11:00:15 -070011130 }
11131 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011132
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070011133 /*
Kenny Root447106f2011-03-23 11:00:15 -070011134 * Look at potentially valid container ids from processCids If package
11135 * information doesn't match the one on record or package scanning fails,
11136 * the cid is added to list of removeCids. We currently don't delete stale
11137 * containers.
11138 */
Kenny Root6dceb882012-04-12 14:23:49 -070011139 private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -070011140 HashSet<String> removeCids) {
11141 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -070011142 Set<AsecInstallArgs> keys = processCids.keySet();
Kenny Root447106f2011-03-23 11:00:15 -070011143 boolean doGc = false;
Kenny Root6dceb882012-04-12 14:23:49 -070011144 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -070011145 String codePath = processCids.get(args);
11146 if (DEBUG_SD_INSTALL)
11147 Log.i(TAG, "Loading container : " + args.cid);
11148 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
11149 try {
11150 // Make sure there are no container errors first.
11151 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
11152 Slog.e(TAG, "Failed to mount cid : " + args.cid
11153 + " when installing from sdcard");
11154 continue;
11155 }
11156 // Check code path here.
11157 if (codePath == null || !codePath.equals(args.getCodePath())) {
11158 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
11159 + " does not match one in settings " + codePath);
11160 continue;
11161 }
11162 // Parse package
Kenny Root51a573c2012-05-17 13:30:28 -070011163 int parseFlags = mDefParseFlags;
11164 if (args.isExternal()) {
11165 parseFlags |= PackageParser.PARSE_ON_SDCARD;
11166 }
Kenny Rootc7a89992012-06-05 15:13:17 -070011167 if (args.isFwdLocked()) {
11168 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
11169 }
Kenny Root51a573c2012-05-17 13:30:28 -070011170
Kenny Root447106f2011-03-23 11:00:15 -070011171 doGc = true;
11172 synchronized (mInstallLock) {
11173 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -070011174 0, 0, null);
Kenny Root447106f2011-03-23 11:00:15 -070011175 // Scan the package
11176 if (pkg != null) {
11177 /*
11178 * TODO why is the lock being held? doPostInstall is
11179 * called in other places without the lock. This needs
11180 * to be straightened out.
11181 */
11182 // writer
11183 synchronized (mPackages) {
11184 retCode = PackageManager.INSTALL_SUCCEEDED;
11185 pkgList.add(pkg.packageName);
11186 // Post process args
Kenny Root6dceb882012-04-12 14:23:49 -070011187 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
11188 pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -070011189 }
11190 } else {
11191 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
11192 }
11193 }
11194
11195 } finally {
11196 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
11197 // Don't destroy container here. Wait till gc clears things
11198 // up.
11199 removeCids.add(args.cid);
11200 }
11201 }
11202 }
11203 // writer
11204 synchronized (mPackages) {
11205 // If the platform SDK has changed since the last time we booted,
11206 // we need to re-grant app permission to catch any new ones that
11207 // appear. This is really a hack, and means that apps can in some
11208 // cases get permissions that the user didn't initially explicitly
11209 // allow... it would be nice to have some better way to handle
11210 // this situation.
11211 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
11212 if (regrantPermissions)
11213 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
11214 + mSdkVersion + "; regranting permissions for external storage");
11215 mSettings.mExternalSdkPlatform = mSdkVersion;
11216
11217 // Make sure group IDs have been assigned, and any permission
11218 // changes in other apps are accounted for
Dianne Hackborne639da72012-02-21 15:11:13 -080011219 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
11220 | (regrantPermissions
11221 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
11222 : 0));
Kenny Root447106f2011-03-23 11:00:15 -070011223 // can downgrade to reader
11224 // Persist settings
11225 mSettings.writeLPr();
11226 }
11227 // Send a broadcast to let everyone know we are done processing
11228 if (pkgList.size() > 0) {
Christopher Tated15967482013-10-04 13:57:22 -070011229 sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null);
Kenny Root447106f2011-03-23 11:00:15 -070011230 }
11231 // Force gc to avoid any stale parser references that we might have.
11232 if (doGc) {
11233 Runtime.getRuntime().gc();
11234 }
11235 // List stale containers and destroy stale temporary containers.
11236 if (removeCids != null) {
11237 for (String cid : removeCids) {
11238 if (cid.startsWith(mTempContainerPrefix)) {
11239 Log.i(TAG, "Destroying stale temporary container " + cid);
11240 PackageHelper.destroySdDir(cid);
11241 } else {
11242 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080011243 }
11244 }
Kenny Root447106f2011-03-23 11:00:15 -070011245 }
11246 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011247
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080011248 /*
Kenny Root447106f2011-03-23 11:00:15 -070011249 * Utility method to unload a list of specified containers
11250 */
Kenny Root6dceb882012-04-12 14:23:49 -070011251 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -070011252 // Just unmount all valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -070011253 for (AsecInstallArgs arg : cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -070011254 synchronized (mInstallLock) {
11255 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080011256 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011257 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011258 }
11259
Kenny Root447106f2011-03-23 11:00:15 -070011260 /*
11261 * Unload packages mounted on external media. This involves deleting package
11262 * data from internal structures, sending broadcasts about diabled packages,
11263 * gc'ing to free up references, unmounting all secure containers
11264 * corresponding to packages on external media, and posting a
11265 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
11266 * that we always have to post this message if status has been requested no
11267 * matter what.
11268 */
Kenny Root6dceb882012-04-12 14:23:49 -070011269 private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -070011270 final boolean reportStatus) {
11271 if (DEBUG_SD_INSTALL)
11272 Log.i(TAG, "unloading media packages");
11273 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -070011274 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
11275 final Set<AsecInstallArgs> keys = processCids.keySet();
11276 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -070011277 String pkgName = args.getPackageName();
11278 if (DEBUG_SD_INSTALL)
11279 Log.i(TAG, "Trying to unload pkg : " + pkgName);
11280 // Delete package internally
11281 PackageRemovedInfo outInfo = new PackageRemovedInfo();
11282 synchronized (mInstallLock) {
Christopher Tateacee6e92013-05-14 16:11:44 -070011283 boolean res = deletePackageLI(pkgName, null, false, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -070011284 PackageManager.DELETE_KEEP_DATA, outInfo, false);
Kenny Root447106f2011-03-23 11:00:15 -070011285 if (res) {
11286 pkgList.add(pkgName);
11287 } else {
11288 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
11289 failedList.add(args);
11290 }
11291 }
11292 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070011293
Kenny Root447106f2011-03-23 11:00:15 -070011294 // reader
11295 synchronized (mPackages) {
11296 // We didn't update the settings after removing each package;
11297 // write them now for all packages.
11298 mSettings.writeLPr();
11299 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070011300
Kenny Root447106f2011-03-23 11:00:15 -070011301 // We have to absolutely send UPDATED_MEDIA_STATUS only
11302 // after confirming that all the receivers processed the ordered
11303 // broadcast when packages get disabled, force a gc to clean things up.
11304 // and unload all the containers.
11305 if (pkgList.size() > 0) {
Christopher Tated15967482013-10-04 13:57:22 -070011306 sendResourcesChangedBroadcast(false, false, pkgList, uidArr,
11307 new IIntentReceiver.Stub() {
Kenny Root447106f2011-03-23 11:00:15 -070011308 public void performReceive(Intent intent, int resultCode, String data,
Dianne Hackborn20e80982012-08-31 19:00:44 -070011309 Bundle extras, boolean ordered, boolean sticky,
11310 int sendingUser) throws RemoteException {
Kenny Root447106f2011-03-23 11:00:15 -070011311 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
11312 reportStatus ? 1 : 0, 1, keys);
11313 mHandler.sendMessage(msg);
11314 }
11315 });
11316 } else {
11317 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
11318 keys);
11319 mHandler.sendMessage(msg);
11320 }
11321 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070011322
Amith Yamasani6ec10122012-08-23 13:49:25 -070011323 /** Binder call */
11324 @Override
Kenny Root447106f2011-03-23 11:00:15 -070011325 public void movePackage(final String packageName, final IPackageMoveObserver observer,
11326 final int flags) {
11327 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
Amith Yamasani6ec10122012-08-23 13:49:25 -070011328 UserHandle user = new UserHandle(UserHandle.getCallingUserId());
Kenny Root447106f2011-03-23 11:00:15 -070011329 int returnCode = PackageManager.MOVE_SUCCEEDED;
11330 int currFlags = 0;
11331 int newFlags = 0;
11332 // reader
11333 synchronized (mPackages) {
11334 PackageParser.Package pkg = mPackages.get(packageName);
11335 if (pkg == null) {
11336 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
11337 } else {
11338 // Disable moving fwd locked apps and system packages
11339 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
11340 Slog.w(TAG, "Cannot move system application");
11341 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root447106f2011-03-23 11:00:15 -070011342 } else if (pkg.mOperationPending) {
11343 Slog.w(TAG, "Attempt to move package which has pending operations");
11344 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
11345 } else {
11346 // Find install location first
11347 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
11348 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
11349 Slog.w(TAG, "Ambigous flags specified for move location.");
11350 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
11351 } else {
11352 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
11353 : PackageManager.INSTALL_INTERNAL;
11354 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
11355 : PackageManager.INSTALL_INTERNAL;
Kenny Rootbf023582012-05-02 16:56:15 -070011356
Kenny Root447106f2011-03-23 11:00:15 -070011357 if (newFlags == currFlags) {
11358 Slog.w(TAG, "No move required. Trying to move to same location");
11359 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Rootbf023582012-05-02 16:56:15 -070011360 } else {
11361 if (isForwardLocked(pkg)) {
11362 currFlags |= PackageManager.INSTALL_FORWARD_LOCK;
11363 newFlags |= PackageManager.INSTALL_FORWARD_LOCK;
11364 }
Kenny Root447106f2011-03-23 11:00:15 -070011365 }
11366 }
11367 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
11368 pkg.mOperationPending = true;
11369 }
11370 }
11371 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080011372
Kenny Root447106f2011-03-23 11:00:15 -070011373 /*
11374 * TODO this next block probably shouldn't be inside the lock. We
11375 * can't guarantee these won't change after this is fired off
11376 * anyway.
11377 */
11378 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Amith Yamasani6ec10122012-08-23 13:49:25 -070011379 processPendingMove(new MoveParams(null, observer, 0, packageName,
11380 null, -1, user),
Kenny Root6dceb882012-04-12 14:23:49 -070011381 returnCode);
Kenny Root447106f2011-03-23 11:00:15 -070011382 } else {
11383 Message msg = mHandler.obtainMessage(INIT_COPY);
11384 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -070011385 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -070011386 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Amith Yamasani6ec10122012-08-23 13:49:25 -070011387 pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user);
Kenny Root447106f2011-03-23 11:00:15 -070011388 msg.obj = mp;
11389 mHandler.sendMessage(msg);
11390 }
11391 }
11392 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080011393
Kenny Root447106f2011-03-23 11:00:15 -070011394 private void processPendingMove(final MoveParams mp, final int currentStatus) {
11395 // Queue up an async operation since the package deletion may take a
11396 // little while.
11397 mHandler.post(new Runnable() {
11398 public void run() {
11399 // TODO fix this; this does nothing.
11400 mHandler.removeCallbacks(this);
11401 int returnCode = currentStatus;
11402 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
11403 int uidArr[] = null;
11404 ArrayList<String> pkgList = null;
11405 synchronized (mPackages) {
11406 PackageParser.Package pkg = mPackages.get(mp.packageName);
11407 if (pkg == null) {
11408 Slog.w(TAG, " Package " + mp.packageName
11409 + " doesn't exist. Aborting move");
11410 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
11411 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
11412 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
11413 + mp.srcArgs.getCodePath() + " to "
11414 + pkg.applicationInfo.sourceDir
11415 + " Aborting move and returning error");
11416 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
11417 } else {
11418 uidArr = new int[] {
11419 pkg.applicationInfo.uid
11420 };
11421 pkgList = new ArrayList<String>();
11422 pkgList.add(mp.packageName);
11423 }
11424 }
11425 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
11426 // Send resources unavailable broadcast
Christopher Tated15967482013-10-04 13:57:22 -070011427 sendResourcesChangedBroadcast(false, true, pkgList, uidArr, null);
Kenny Root447106f2011-03-23 11:00:15 -070011428 // Update package code and resource paths
11429 synchronized (mInstallLock) {
11430 synchronized (mPackages) {
11431 PackageParser.Package pkg = mPackages.get(mp.packageName);
11432 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -070011433 if (pkg == null) {
11434 Slog.w(TAG, " Package " + mp.packageName
11435 + " doesn't exist. Aborting move");
11436 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -070011437 } else if (!mp.srcArgs.getCodePath().equals(
11438 pkg.applicationInfo.sourceDir)) {
11439 Slog.w(TAG, "Package " + mp.packageName
11440 + " code path changed from " + mp.srcArgs.getCodePath()
11441 + " to " + pkg.applicationInfo.sourceDir
11442 + " Aborting move and returning error");
11443 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
11444 } else {
11445 final String oldCodePath = pkg.mPath;
11446 final String newCodePath = mp.targetArgs.getCodePath();
11447 final String newResPath = mp.targetArgs.getResourcePath();
11448 final String newNativePath = mp.targetArgs
11449 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -070011450
Kenny Rootddbe50d2012-09-06 13:18:37 -070011451 final File newNativeDir = new File(newNativePath);
Kenny Rootbf023582012-05-02 16:56:15 -070011452
Kenny Rootddbe50d2012-09-06 13:18:37 -070011453 if (!isForwardLocked(pkg) && !isExternal(pkg)) {
Kenny Roota3e90792012-10-18 10:58:36 -070011454 NativeLibraryHelper.copyNativeBinariesIfNeededLI(
11455 new File(newCodePath), newNativeDir);
11456 }
11457 final int[] users = sUserManager.getUserIds();
11458 for (int user : users) {
11459 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
11460 newNativePath, user) < 0) {
11461 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
Kenny Rootddbe50d2012-09-06 13:18:37 -070011462 }
Kenny Root6a6b0072010-10-07 16:46:10 -070011463 }
11464
11465 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
11466 pkg.mPath = newCodePath;
11467 // Move dex files around
11468 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
11469 // Moving of dex files failed. Set
11470 // error code and abort move.
11471 pkg.mPath = pkg.mScanPath;
11472 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
11473 }
11474 }
11475
11476 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -070011477 pkg.mScanPath = newCodePath;
11478 pkg.applicationInfo.sourceDir = newCodePath;
11479 pkg.applicationInfo.publicSourceDir = newResPath;
11480 pkg.applicationInfo.nativeLibraryDir = newNativePath;
11481 PackageSetting ps = (PackageSetting) pkg.mExtras;
11482 ps.codePath = new File(pkg.applicationInfo.sourceDir);
11483 ps.codePathString = ps.codePath.getPath();
11484 ps.resourcePath = new File(
11485 pkg.applicationInfo.publicSourceDir);
11486 ps.resourcePathString = ps.resourcePath.getPath();
11487 ps.nativeLibraryPathString = newNativePath;
11488 // Set the application info flag
11489 // correctly.
11490 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
11491 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
11492 } else {
11493 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
11494 }
11495 ps.setFlags(pkg.applicationInfo.flags);
11496 mAppDirs.remove(oldCodePath);
11497 mAppDirs.put(newCodePath, pkg);
11498 // Persist settings
11499 mSettings.writeLPr();
11500 }
11501 }
11502 }
11503 }
11504 // Send resources available broadcast
Christopher Tated15967482013-10-04 13:57:22 -070011505 sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null);
Kenny Root447106f2011-03-23 11:00:15 -070011506 }
11507 }
11508 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
11509 // Clean up failed installation
11510 if (mp.targetArgs != null) {
Kenny Root6dceb882012-04-12 14:23:49 -070011511 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
11512 -1);
Kenny Root447106f2011-03-23 11:00:15 -070011513 }
11514 } else {
11515 // Force a gc to clear things up.
11516 Runtime.getRuntime().gc();
11517 // Delete older code
11518 synchronized (mInstallLock) {
11519 mp.srcArgs.doPostDeleteLI(true);
11520 }
11521 }
Kenny Rootdeb11262010-08-02 11:36:21 -070011522
Kenny Root447106f2011-03-23 11:00:15 -070011523 // Allow more operations on this file if we didn't fail because
11524 // an operation was already pending for this package.
11525 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
11526 synchronized (mPackages) {
11527 PackageParser.Package pkg = mPackages.get(mp.packageName);
11528 if (pkg != null) {
11529 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -070011530 }
11531 }
Kenny Root447106f2011-03-23 11:00:15 -070011532 }
Kenny Rootdeb11262010-08-02 11:36:21 -070011533
Kenny Root447106f2011-03-23 11:00:15 -070011534 IPackageMoveObserver observer = mp.observer;
11535 if (observer != null) {
11536 try {
11537 observer.packageMoved(mp.packageName, returnCode);
11538 } catch (RemoteException e) {
11539 Log.i(TAG, "Observer no longer exists.");
11540 }
11541 }
11542 }
11543 });
11544 }
11545
11546 public boolean setInstallLocation(int loc) {
11547 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
11548 null);
11549 if (getInstallLocation() == loc) {
11550 return true;
11551 }
11552 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
11553 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
Jeff Sharkey625239a2012-09-26 22:03:49 -070011554 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
11555 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
Kenny Root447106f2011-03-23 11:00:15 -070011556 return true;
11557 }
11558 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080011559 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -070011560
Kenny Root447106f2011-03-23 11:00:15 -070011561 public int getInstallLocation() {
Jeff Sharkey625239a2012-09-26 22:03:49 -070011562 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
11563 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION,
Kenny Root447106f2011-03-23 11:00:15 -070011564 PackageHelper.APP_INSTALL_AUTO);
11565 }
Amith Yamasani0b285492011-04-14 17:35:23 -070011566
Amith Yamasani258848d2012-08-10 17:06:33 -070011567 /** Called by UserManagerService */
Dianne Hackborn4428e172012-08-24 17:43:05 -070011568 void cleanUpUserLILPw(int userHandle) {
Christopher Tate1e08f5c2013-05-02 13:27:27 -070011569 mDirtyUsers.remove(userHandle);
Dianne Hackborn4428e172012-08-24 17:43:05 -070011570 mSettings.removeUserLPr(userHandle);
Christopher Tate1e08f5c2013-05-02 13:27:27 -070011571 mPendingBroadcasts.remove(userHandle);
Dianne Hackborn4428e172012-08-24 17:43:05 -070011572 if (mInstaller != null) {
11573 // Technically, we shouldn't be doing this with the package lock
11574 // held. However, this is very rare, and there is already so much
11575 // other disk I/O going on, that we'll let it slide for now.
11576 mInstaller.removeUserDataDirs(userHandle);
11577 }
11578 }
11579
11580 /** Called by UserManagerService */
11581 void createNewUserLILPw(int userHandle, File path) {
11582 if (mInstaller != null) {
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080011583 mSettings.createNewUserLILPw(this, mInstaller, userHandle, path);
Amith Yamasani13593602012-03-22 16:16:17 -070011584 }
11585 }
11586
Kenny Root0aaa0d92011-09-12 16:42:55 -070011587 @Override
11588 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
11589 mContext.enforceCallingOrSelfPermission(
11590 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
11591 "Only package verification agents can read the verifier device identity");
11592
11593 synchronized (mPackages) {
11594 return mSettings.getVerifierDeviceIdentityLPw();
11595 }
11596 }
Amith Yamasani742a6712011-05-04 14:49:28 -070011597
Amith Yamasani13593602012-03-22 16:16:17 -070011598 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -070011599 public void setPermissionEnforced(String permission, boolean enforced) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011600 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
11601 if (READ_EXTERNAL_STORAGE.equals(permission)) {
11602 synchronized (mPackages) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -070011603 if (mSettings.mReadExternalStorageEnforced == null
11604 || mSettings.mReadExternalStorageEnforced != enforced) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -070011605 mSettings.mReadExternalStorageEnforced = enforced;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011606 mSettings.writeLPr();
Dianne Hackbornf1b78242013-04-08 22:28:59 -070011607 }
11608 }
11609 // kill any non-foreground processes so we restart them and
11610 // grant/revoke the GID.
11611 final IActivityManager am = ActivityManagerNative.getDefault();
11612 if (am != null) {
11613 final long token = Binder.clearCallingIdentity();
11614 try {
11615 am.killProcessesBelowForeground("setPermissionEnforcement");
11616 } catch (RemoteException e) {
11617 } finally {
11618 Binder.restoreCallingIdentity(token);
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011619 }
11620 }
11621 } else {
11622 throw new IllegalArgumentException("No selective enforcement for " + permission);
11623 }
11624 }
11625
11626 @Override
Jeff Sharkey02e4d16e2013-08-12 20:31:36 -070011627 @Deprecated
Jeff Sharkey5d32e772012-04-12 15:59:23 -070011628 public boolean isPermissionEnforced(String permission) {
Jeff Sharkey02e4d16e2013-08-12 20:31:36 -070011629 return true;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011630 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070011631
Adam Lesinskief2ea1f2013-12-05 16:48:06 -080011632 @Override
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070011633 public boolean isStorageLow() {
11634 final long token = Binder.clearCallingIdentity();
11635 try {
Adam Lesinskief2ea1f2013-12-05 16:48:06 -080011636 final DeviceStorageMonitorInternal
11637 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
11638 if (dsm != null) {
11639 return dsm.isMemoryLow();
11640 } else {
11641 return false;
11642 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070011643 } finally {
11644 Binder.restoreCallingIdentity(token);
11645 }
11646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647}