blob: ef1d2589202c37e6eb545e1994a6646d804a7cd9 [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 Lesinski182f73f2013-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 Lesinski182f73f2013-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 Lesinski182f73f2013-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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700223 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700224
Kenny Root5ab21572011-07-27 11:11:19 -0700225 /**
Christopher Tatee6f81cf2013-10-23 17:28:27 -0700226 * Timeout (in milliseconds) after which the watchdog should declare that
227 * our handler thread is wedged. The usual default for such things is one
228 * minute but we sometimes do very lengthy I/O operations on this thread,
229 * such as installing multi-gigabyte applications, so ours needs to be longer.
230 */
231 private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes
232
233 /**
Kenny Root5ab21572011-07-27 11:11:19 -0700234 * Whether verification is enabled by default.
235 */
rich cannings36c67c22012-09-16 16:20:23 -0700236 private static final boolean DEFAULT_VERIFY_ENABLE = true;
Kenny Root5ab21572011-07-27 11:11:19 -0700237
238 /**
239 * The default maximum time to wait for the verification agent to return in
240 * milliseconds.
241 */
rich canningsaa8513e2012-05-21 16:15:23 -0700242 private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
Kenny Root5ab21572011-07-27 11:11:19 -0700243
rich canningsa6cfe522012-05-21 15:50:56 -0700244 /**
245 * The default response for package verification timeout.
246 *
247 * This can be either PackageManager.VERIFICATION_ALLOW or
248 * PackageManager.VERIFICATION_REJECT.
249 */
250 private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
251
Kenny Root11128572010-10-11 10:51:32 -0700252 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
253
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800254 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700255 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800256 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700257
Kenny Root05ca4c92011-09-15 10:36:25 -0700258 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
259
Kenny Root85387d72010-08-26 10:13:11 -0700260 private static final String LIB_DIR_NAME = "lib";
261
Kenny Rootc78a8072010-07-27 15:18:38 -0700262 static final String mTempContainerPrefix = "smdl2tmp";
263
Jeff Brown6f357d32014-01-15 20:40:55 -0800264 final ServiceThread mHandlerThread;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700265 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266
Dianne Hackborn851a5412009-05-08 12:06:44 -0700267 final int mSdkVersion = Build.VERSION.SDK_INT;
268 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
269 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 final Context mContext;
272 final boolean mFactoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700273 final boolean mOnlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700274 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 final DisplayMetrics mMetrics;
276 final int mDefParseFlags;
277 final String[] mSeparateProcesses;
278
279 // This is where all application persistent data goes.
280 final File mAppDataDir;
281
Amith Yamasani0b285492011-04-14 17:35:23 -0700282 // This is where all application persistent data goes for secondary users.
283 final File mUserAppDataDir;
284
Kenny Root51a573c2012-05-17 13:30:28 -0700285 /** The location for ASEC container files on internal storage. */
286 final String mAsecInternalPath;
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 // This is the object monitoring the framework dir.
289 final FileObserver mFrameworkInstallObserver;
290
291 // This is the object monitoring the system app dir.
292 final FileObserver mSystemInstallObserver;
293
Christopher Tateccbf84f2013-05-08 15:25:41 -0700294 // This is the object monitoring the privileged system app dir.
295 final FileObserver mPrivilegedInstallObserver;
296
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700297 // This is the object monitoring the system app dir.
298 final FileObserver mVendorInstallObserver;
299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 // This is the object monitoring mAppInstallDir.
301 final FileObserver mAppInstallObserver;
302
303 // This is the object monitoring mDrmAppPrivateInstallDir.
304 final FileObserver mDrmAppInstallObserver;
305
Kenny Rootddbe50d2012-09-06 13:18:37 -0700306 // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 // LOCK HELD. Can be called with mInstallLock held.
308 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 final File mAppInstallDir;
311
Kenny Rootddbe50d2012-09-06 13:18:37 -0700312 /**
313 * Directory to which applications installed internally have native
314 * libraries copied.
315 */
316 private File mAppLibInstallDir;
317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
319 // apps.
320 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 // Lock for state used when installing and doing other long running
325 // operations. Methods that must be called with this lock held have
326 // the prefix "LI".
327 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 // These are the directories in the 3rd party applications installed dir
330 // that we have currently loaded packages from. Keys are the application's
331 // installed zip file (absolute codePath), and values are Package.
332 final HashMap<String, PackageParser.Package> mAppDirs =
333 new HashMap<String, PackageParser.Package>();
334
335 // Information for the parser to write more useful error messages.
336 File mScanningPath;
337 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);
871 sendResourcesChangedBroadcast(true, false,
872 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 Lesinski182f73f2013-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 Lesinski182f73f2013-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 mScanningPath = scanFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
4161 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
4162 }
4163
Christopher Tateccbf84f2013-05-08 15:25:41 -07004164 if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
4165 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED;
4166 }
4167
Jose Limabb9682e2013-08-16 16:14:32 -07004168 if (mCustomResolverComponentName != null &&
4169 mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
4170 setUpCustomResolverActivity(pkg);
4171 }
4172
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004173 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 synchronized (mPackages) {
4175 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004176 Slog.w(TAG, "*************************************************");
4177 Slog.w(TAG, "Core android package being redefined. Skipping.");
4178 Slog.w(TAG, " file=" + mScanningPath);
4179 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
4181 return null;
4182 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004183
Jose Limabb9682e2013-08-16 16:14:32 -07004184 // Set up information for our fall-back user intent resolution activity.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 mPlatformPackage = pkg;
4186 pkg.mVersionCode = mSdkVersion;
4187 mAndroidApplication = pkg.applicationInfo;
Jose Limabb9682e2013-08-16 16:14:32 -07004188
4189 if (!mResolverReplaced) {
4190 mResolveActivity.applicationInfo = mAndroidApplication;
4191 mResolveActivity.name = ResolverActivity.class.getName();
4192 mResolveActivity.packageName = mAndroidApplication.packageName;
4193 mResolveActivity.processName = "system:ui";
4194 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4195 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4196 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
4197 mResolveActivity.exported = true;
4198 mResolveActivity.enabled = true;
4199 mResolveInfo.activityInfo = mResolveActivity;
4200 mResolveInfo.priority = 0;
4201 mResolveInfo.preferredOrder = 0;
4202 mResolveInfo.match = 0;
4203 mResolveComponentName = new ComponentName(
4204 mAndroidApplication.packageName, mResolveActivity.name);
4205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 }
4207 }
4208
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004209 if (DEBUG_PACKAGE_SCANNING) {
4210 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4211 Log.d(TAG, "Scanning package " + pkg.packageName);
4212 }
4213
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004214 if (mPackages.containsKey(pkg.packageName)
4215 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004216 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
4219 return null;
4220 }
4221
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004222 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004223 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
4224 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 SharedUserSetting suid = null;
4227 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004228
Kenny Root502e9a42011-01-10 13:48:15 -08004229 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004230 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08004231 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004232 pkg.mRealPackage = null;
4233 pkg.mAdoptPermissions = null;
4234 }
Kenny Root502e9a42011-01-10 13:48:15 -08004235
Kenny Root447106f2011-03-23 11:00:15 -07004236 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 synchronized (mPackages) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07004238 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
4239 // Check all shared libraries and map to their actual file path.
4240 // We only do this here for apps not on a system dir, because those
4241 // are the only ones that can fail an install due to this. We
4242 // will take care of the system apps by updating all of their
4243 // library paths after the scan is done.
4244 if (!updateSharedLibrariesLPw(pkg, null)) {
4245 return null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004246 }
Kenny Root1683afa2011-01-07 14:27:50 -08004247 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 if (pkg.mSharedUserId != null) {
Ben Gruverdd72c9e2013-08-06 12:34:17 -07004250 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004252 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 + " for shared user failed");
4254 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4255 return null;
4256 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004257 if (DEBUG_PACKAGE_SCANNING) {
4258 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4259 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
4260 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 }
4262 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004263
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004264 // Check if we are renaming from an original package name.
4265 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004266 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08004267 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004268 // This package may need to be renamed to a previously
4269 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07004270 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08004271 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004272 // This package had originally been installed as the
4273 // original name, and we have already taken care of
4274 // transitioning to the new one. Just update the new
4275 // one to continue using the old name.
4276 realName = pkg.mRealPackage;
4277 if (!pkg.packageName.equals(renamed)) {
4278 // Callers into this function may have already taken
4279 // care of renaming the package; only do it here if
4280 // it is not already done.
4281 pkg.setPackageName(renamed);
4282 }
4283
Dianne Hackbornc1552392010-03-03 16:19:01 -08004284 } else {
4285 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07004286 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08004287 pkg.mOriginalPackages.get(i))) != null) {
4288 // We do have the package already installed under its
4289 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07004290 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08004291 // New package is not compatible with original.
4292 origPackage = null;
4293 continue;
4294 } else if (origPackage.sharedUser != null) {
4295 // Make sure uid is compatible between packages.
4296 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004297 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08004298 + " to " + pkg.packageName + ": old uid "
4299 + origPackage.sharedUser.name
4300 + " differs from " + pkg.mSharedUserId);
4301 origPackage = null;
4302 continue;
4303 }
4304 } else {
4305 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
4306 + pkg.packageName + " to old name " + origPackage.name);
4307 }
4308 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004309 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004310 }
4311 }
4312 }
4313
4314 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004315 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004316 + " was transferred to another, but its .apk remains");
4317 }
4318
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004319 // Just create the setting, don't add it yet. For already existing packages
4320 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07004321 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07004322 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004323 pkg.applicationInfo.flags, user, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004325 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004326 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4327 return null;
4328 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004329
4330 if (pkgSetting.origPackage != null) {
4331 // If we are first transitioning from an original package,
4332 // fix up the new package's name now. We need to do this after
4333 // looking up the package under its new name, so getPackageLP
4334 // can take care of fiddling things correctly.
4335 pkg.setPackageName(origPackage.name);
4336
4337 // File a report about this.
4338 String msg = "New package " + pkgSetting.realName
4339 + " renamed to replace old package " + pkgSetting.name;
4340 reportSettingsProblem(Log.WARN, msg);
4341
4342 // Make a note of it.
4343 mTransferedPackages.add(origPackage.name);
4344
4345 // No longer need to retain this.
4346 pkgSetting.origPackage = null;
4347 }
4348
4349 if (realName != null) {
4350 // Make a note of it.
4351 mTransferedPackages.add(pkg.packageName);
4352 }
4353
Kenny Rootc52d6fd2012-05-07 23:04:52 -07004354 if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
4356 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004357
Robert Craig0f40dc92013-03-25 06:33:03 -04004358 if (mFoundPolicyFile) {
4359 SELinuxMMAC.assignSeinfoValue(pkg);
4360 }
4361
Amith Yamasani13593602012-03-22 16:16:17 -07004362 pkg.applicationInfo.uid = pkgSetting.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004364
Suchi Amalapurapuae181712010-03-30 14:01:02 -07004365 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004366 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 return null;
4368 }
4369 // The signature has changed, but this package is in the system
4370 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07004371 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 // However... if this package is part of a shared user, but it
4373 // doesn't match the signature of the shared user, let's fail.
4374 // What this means is that you can't change the signatures
4375 // associated with an overall shared user, which doesn't seem all
4376 // that unreasonable.
4377 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004378 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07004379 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
4380 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4382 return null;
4383 }
4384 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004385 // File a report about this.
4386 String msg = "System package " + pkg.packageName
4387 + " signature changed; retaining data.";
4388 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004389 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004390
The Android Open Source Project10592532009-03-18 17:39:46 -07004391 // Verify that this new package doesn't have any content providers
4392 // that conflict with existing packages. Only do this if the
4393 // package isn't already installed, since we don't want to break
4394 // things that are installed.
4395 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08004396 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07004397 int i;
4398 for (i=0; i<N; i++) {
4399 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004400 if (p.info.authority != null) {
4401 String names[] = p.info.authority.split(";");
4402 for (int j = 0; j < names.length; j++) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004403 if (mProvidersByAuthority.containsKey(names[j])) {
4404 PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004405 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004406 " (in package " + pkg.applicationInfo.packageName +
4407 ") is already used by "
4408 + ((other != null && other.getComponentName() != null)
4409 ? other.getComponentName().getPackageName() : "?"));
4410 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
4411 return null;
4412 }
The Android Open Source Project10592532009-03-18 17:39:46 -07004413 }
4414 }
4415 }
4416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417
Kenny Root447106f2011-03-23 11:00:15 -07004418 if (pkg.mAdoptPermissions != null) {
4419 // This package wants to adopt ownership of permissions from
4420 // another package.
4421 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
4422 final String origName = pkg.mAdoptPermissions.get(i);
4423 final PackageSetting orig = mSettings.peekPackageLPr(origName);
4424 if (orig != null) {
4425 if (verifyPackageUpdateLPr(orig, pkg)) {
4426 Slog.i(TAG, "Adopting permissions from " + origName + " to "
4427 + pkg.packageName);
4428 mSettings.transferPermissionsLPw(origName, pkg.packageName);
4429 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004430 }
4431 }
4432 }
4433 }
Kenny Root447106f2011-03-23 11:00:15 -07004434
4435 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004436
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004437 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 pkg.applicationInfo.processName = fixProcessName(
4440 pkg.applicationInfo.packageName,
4441 pkg.applicationInfo.processName,
4442 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443
4444 File dataPath;
4445 if (mPlatformPackage == pkg) {
4446 // The system package is special.
4447 dataPath = new File (Environment.getDataDirectory(), "system");
4448 pkg.applicationInfo.dataDir = dataPath.getPath();
4449 } else {
4450 // This is a normal package, need to make its data directory.
Dave Burke383fa182012-10-23 23:12:19 -07004451 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07004452
Dave Burke383fa182012-10-23 23:12:19 -07004453 boolean uidError = false;
4454
4455 if (dataPath.exists()) {
4456 int currentUid = 0;
4457 try {
4458 StructStat stat = Libcore.os.stat(dataPath.getPath());
4459 currentUid = stat.st_uid;
4460 } catch (ErrnoException e) {
4461 Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004463
Dave Burke383fa182012-10-23 23:12:19 -07004464 // If we have mismatched owners for the data path, we have a problem.
4465 if (currentUid != pkg.applicationInfo.uid) {
4466 boolean recovered = false;
4467 if (currentUid == 0) {
4468 // The directory somehow became owned by root. Wow.
4469 // This is probably because the system was stopped while
4470 // installd was in the middle of messing with its libs
4471 // directory. Ask installd to fix that.
4472 int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
4473 pkg.applicationInfo.uid);
4474 if (ret >= 0) {
4475 recovered = true;
4476 String msg = "Package " + pkg.packageName
4477 + " unexpectedly changed to uid 0; recovered to " +
4478 + pkg.applicationInfo.uid;
4479 reportSettingsProblem(Log.WARN, msg);
4480 }
4481 }
4482 if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
4483 || (scanMode&SCAN_BOOTING) != 0)) {
4484 // If this is a system app, we can at least delete its
4485 // current data so the application will still work.
4486 int ret = removeDataDirsLI(pkgName);
4487 if (ret >= 0) {
4488 // TODO: Kill the processes first
4489 // Old data gone!
4490 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
4491 ? "System package " : "Third party package ";
4492 String msg = prefix + pkg.packageName
4493 + " has changed from uid: "
4494 + currentUid + " to "
4495 + pkg.applicationInfo.uid + "; old data erased";
4496 reportSettingsProblem(Log.WARN, msg);
4497 recovered = true;
4498
4499 // And now re-install the app.
Robert Craig0f40dc92013-03-25 06:33:03 -04004500 ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
4501 pkg.applicationInfo.seinfo);
Dave Burke383fa182012-10-23 23:12:19 -07004502 if (ret == -1) {
4503 // Ack should not happen!
4504 msg = prefix + pkg.packageName
4505 + " could not have data directory re-created after delete.";
4506 reportSettingsProblem(Log.WARN, msg);
4507 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4508 return null;
4509 }
4510 }
4511 if (!recovered) {
4512 mHasSystemUidErrors = true;
4513 }
4514 } else if (!recovered) {
4515 // If we allow this install to proceed, we will be broken.
4516 // Abort, abort!
4517 mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED;
4518 return null;
4519 }
4520 if (!recovered) {
4521 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
4522 + pkg.applicationInfo.uid + "/fs_"
4523 + currentUid;
4524 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
4525 String msg = "Package " + pkg.packageName
4526 + " has mismatched uid: "
4527 + currentUid + " on disk, "
4528 + pkg.applicationInfo.uid + " in settings";
4529 // writer
4530 synchronized (mPackages) {
4531 mSettings.mReadMessages.append(msg);
4532 mSettings.mReadMessages.append('\n');
4533 uidError = true;
4534 if (!pkgSetting.uidError) {
4535 reportSettingsProblem(Log.ERROR, msg);
4536 }
4537 }
4538 }
4539 }
Kenny Root4525f5b2012-10-22 14:24:23 -07004540 pkg.applicationInfo.dataDir = dataPath.getPath();
Dave Burke383fa182012-10-23 23:12:19 -07004541 } else {
4542 if (DEBUG_PACKAGE_SCANNING) {
4543 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4544 Log.v(TAG, "Want this data dir: " + dataPath);
4545 }
Nick Kralevich15069212013-01-09 15:54:56 -08004546 //invoke installer to do the actual installation
Robert Craig0f40dc92013-03-25 06:33:03 -04004547 int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
4548 pkg.applicationInfo.seinfo);
Dave Burke383fa182012-10-23 23:12:19 -07004549 if (ret < 0) {
4550 // Error from installer
4551 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4552 return null;
4553 }
4554
4555 if (dataPath.exists()) {
4556 pkg.applicationInfo.dataDir = dataPath.getPath();
4557 } else {
4558 Slog.w(TAG, "Unable to create data directory: " + dataPath);
4559 pkg.applicationInfo.dataDir = null;
4560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 }
Kenny Root85387d72010-08-26 10:13:11 -07004562
4563 /*
Dave Burke383fa182012-10-23 23:12:19 -07004564 * Set the data dir to the default "/data/data/<package name>/lib"
4565 * if we got here without anyone telling us different (e.g., apps
4566 * stored on SD card have their native libraries stored in the ASEC
4567 * container with the APK).
4568 *
4569 * This happens during an upgrade from a package settings file that
4570 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07004571 */
Dave Burke383fa182012-10-23 23:12:19 -07004572 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
Kenny Rootbd135c12010-10-05 12:26:27 -07004573 if (pkgSetting.nativeLibraryPathString == null) {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004574 setInternalAppNativeLibraryPath(pkg, pkgSetting);
Kenny Rootbd135c12010-10-05 12:26:27 -07004575 } else {
4576 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
4577 }
Kenny Root85387d72010-08-26 10:13:11 -07004578 }
Dave Burke383fa182012-10-23 23:12:19 -07004579
4580 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 }
4582
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004583 String path = scanFile.getPath();
4584 /* Note: We don't want to unpack the native binaries for
4585 * system applications, unless they have been updated
4586 * (the binaries are already under /system/lib).
4587 * Also, don't unpack libs for apps on the external card
4588 * since they should have their libraries in the ASEC
4589 * container already.
4590 *
4591 * In other words, we're going to unpack the binaries
4592 * only for non-system apps and system app upgrades.
4593 */
4594 if (pkg.applicationInfo.nativeLibraryDir != null) {
4595 try {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004596 File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
Kenny Root5832ead2011-08-02 15:47:08 -07004597 final String dataPathString = dataPath.getCanonicalPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07004598
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004599 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
4600 /*
4601 * Upgrading from a previous version of the OS sometimes
4602 * leaves native libraries in the /data/data/<app>/lib
4603 * directory for system apps even when they shouldn't be.
4604 * Recent changes in the JNI library search path
4605 * necessitates we remove those to match previous behavior.
4606 */
4607 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
4608 Log.i(TAG, "removed obsolete native libraries for system package "
4609 + path);
Kenny Root831baa22010-10-05 12:29:25 -07004610 }
Kenny Roota3e90792012-10-18 10:58:36 -07004611 } else {
4612 if (!isForwardLocked(pkg) && !isExternal(pkg)) {
4613 /*
4614 * Update native library dir if it starts with
4615 * /data/data
4616 */
4617 if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
4618 setInternalAppNativeLibraryPath(pkg, pkgSetting);
4619 nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
4620 }
Kenny Root66269ea2011-07-12 14:14:01 -07004621
Kenny Roota3e90792012-10-18 10:58:36 -07004622 try {
4623 if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
4624 Slog.e(TAG, "Unable to copy native libraries");
4625 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4626 return null;
4627 }
4628 } catch (IOException e) {
4629 Slog.e(TAG, "Unable to copy native libraries", e);
Kenny Rootddbe50d2012-09-06 13:18:37 -07004630 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4631 return null;
4632 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07004633 }
4634
Dianne Hackborn40e9f292012-11-27 19:12:23 -08004635 if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
Kenny Roota3e90792012-10-18 10:58:36 -07004636 final int[] userIds = sUserManager.getUserIds();
4637 synchronized (mInstallLock) {
4638 for (int userId : userIds) {
4639 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
4640 pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
4641 Slog.w(TAG, "Failed linking native library dir (user=" + userId
4642 + ")");
4643 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4644 return null;
4645 }
4646 }
Nick Kralevich7de350a2012-09-07 15:48:11 -07004647 }
Kenny Root831baa22010-10-05 12:29:25 -07004648 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004649 } catch (IOException ioe) {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004650 Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004652 }
4653 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004654
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004655 if ((scanMode&SCAN_NO_DEX) == 0) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07004656 if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
Dianne Hackborn661cd522011-08-22 00:26:20 -07004657 == DEX_OPT_FAILED) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004658 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
4659 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004660 }
4661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 if (mFactoryTest && pkg.requestedPermissions.contains(
4664 android.Manifest.permission.FACTORY_TEST)) {
4665 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
4666 }
4667
Dianne Hackbornc895be72013-03-11 17:48:43 -07004668 ArrayList<PackageParser.Package> clientLibPkgs = null;
4669
4670 // writer
4671 synchronized (mPackages) {
4672 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
4673 // Only system apps can add new shared libraries.
4674 if (pkg.libraryNames != null) {
4675 for (int i=0; i<pkg.libraryNames.size(); i++) {
4676 String name = pkg.libraryNames.get(i);
4677 boolean allowed = false;
4678 if (isUpdatedSystemApp(pkg)) {
4679 // New library entries can only be added through the
4680 // system image. This is important to get rid of a lot
4681 // of nasty edge cases: for example if we allowed a non-
4682 // system update of the app to add a library, then uninstalling
4683 // the update would make the library go away, and assumptions
4684 // we made such as through app install filtering would now
4685 // have allowed apps on the device which aren't compatible
4686 // with it. Better to just have the restriction here, be
4687 // conservative, and create many fewer cases that can negatively
4688 // impact the user experience.
4689 final PackageSetting sysPs = mSettings
4690 .getDisabledSystemPkgLPr(pkg.packageName);
4691 if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
4692 for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
4693 if (name.equals(sysPs.pkg.libraryNames.get(j))) {
4694 allowed = true;
4695 allowed = true;
4696 break;
4697 }
4698 }
4699 }
4700 } else {
4701 allowed = true;
4702 }
4703 if (allowed) {
4704 if (!mSharedLibraries.containsKey(name)) {
4705 mSharedLibraries.put(name, new SharedLibraryEntry(null,
4706 pkg.packageName));
4707 } else if (!name.equals(pkg.packageName)) {
4708 Slog.w(TAG, "Package " + pkg.packageName + " library "
4709 + name + " already exists; skipping");
4710 }
4711 } else {
4712 Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
4713 + name + " that is not declared on system image; skipping");
4714 }
4715 }
4716 if ((scanMode&SCAN_BOOTING) == 0) {
4717 // If we are not booting, we need to update any applications
4718 // that are clients of our shared library. If we are booting,
4719 // this will all be done once the scan is complete.
4720 clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
4721 }
4722 }
4723 }
4724 }
4725
4726 // We also need to dexopt any apps that are dependent on this library. Note that
4727 // if these fail, we should abort the install since installing the library will
4728 // result in some apps being broken.
4729 if (clientLibPkgs != null) {
4730 if ((scanMode&SCAN_NO_DEX) == 0) {
4731 for (int i=0; i<clientLibPkgs.size(); i++) {
4732 PackageParser.Package clientPkg = clientLibPkgs.get(i);
4733 if (performDexOptLI(clientPkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
4734 == DEX_OPT_FAILED) {
4735 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
4736 return null;
4737 }
4738 }
4739 }
4740 }
4741
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004742 // Request the ActivityManager to kill the process(only for existing packages)
4743 // so that we do not end up in a confused state while the user is still using the older
4744 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004745 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Christopher Tated15967482013-10-04 13:57:22 -07004746 // If the package lives in an asec, tell everyone that the container is going
4747 // away so they can clean up any references to its resources (which would prevent
4748 // vold from being able to unmount the asec)
4749 if (isForwardLocked(pkg) || isExternal(pkg)) {
4750 if (DEBUG_INSTALL) {
4751 Slog.i(TAG, "upgrading pkg " + pkg + " is ASEC-hosted -> UNAVAILABLE");
4752 }
4753 final int[] uidArray = new int[] { pkg.applicationInfo.uid };
4754 final ArrayList<String> pkgList = new ArrayList<String>(1);
4755 pkgList.add(pkg.applicationInfo.packageName);
4756 sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
4757 }
4758
4759 // Post the request that it be killed now that the going-away broadcast is en route
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004760 killApplication(pkg.applicationInfo.packageName,
Dianne Hackborn21d9b562013-05-28 17:46:59 -07004761 pkg.applicationInfo.uid, "update pkg");
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004762 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004763
Dianne Hackbornc895be72013-03-11 17:48:43 -07004764 // Also need to kill any apps that are dependent on the library.
4765 if (clientLibPkgs != null) {
4766 for (int i=0; i<clientLibPkgs.size(); i++) {
4767 PackageParser.Package clientPkg = clientLibPkgs.get(i);
4768 killApplication(clientPkg.applicationInfo.packageName,
Dianne Hackborn21d9b562013-05-28 17:46:59 -07004769 clientPkg.applicationInfo.uid, "update lib");
Dianne Hackbornc895be72013-03-11 17:48:43 -07004770 }
4771 }
4772
Kenny Root447106f2011-03-23 11:00:15 -07004773 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004775 // We don't expect installation to fail beyond this point,
4776 if ((scanMode&SCAN_MONITOR) != 0) {
4777 mAppDirs.put(pkg.mPath, pkg);
4778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07004780 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004781 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004782 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004783 // Make sure we don't accidentally delete its data.
Jeff Sharkey752cd922012-09-23 16:25:12 -07004784 final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
4785 while (iter.hasNext()) {
4786 PackageCleanItem item = iter.next();
4787 if (pkgName.equals(item.packageName)) {
4788 iter.remove();
4789 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004790 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07004791
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004792 // Take care of first install / last update times.
4793 if (currentTime != 0) {
4794 if (pkgSetting.firstInstallTime == 0) {
4795 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
4796 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
4797 pkgSetting.lastUpdateTime = currentTime;
4798 }
4799 } else if (pkgSetting.firstInstallTime == 0) {
4800 // We need *something*. Take time time stamp of the file.
4801 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
4802 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
4803 if (scanFileTime != pkgSetting.timeStamp) {
4804 // A package on the system image has changed; consider this
4805 // to be an update.
4806 pkgSetting.lastUpdateTime = scanFileTime;
4807 }
4808 }
4809
Geremy Condraf1bcca82013-01-07 22:35:24 -08004810 // Add the package's KeySets to the global KeySetManager
4811 KeySetManager ksm = mSettings.mKeySetManager;
4812 try {
4813 ksm.addSigningKeySetToPackage(pkg.packageName, pkg.mSigningKeys);
4814 if (pkg.mKeySetMapping != null) {
4815 for (Map.Entry<String, Set<PublicKey>> entry : pkg.mKeySetMapping.entrySet()) {
4816 if (entry.getValue() != null) {
4817 ksm.addDefinedKeySetToPackage(pkg.packageName,
4818 entry.getValue(), entry.getKey());
4819 }
4820 }
4821 }
4822 } catch (NullPointerException e) {
4823 Slog.e(TAG, "Could not add KeySet to " + pkg.packageName, e);
4824 } catch (IllegalArgumentException e) {
4825 Slog.e(TAG, "Could not add KeySet to malformed package" + pkg.packageName, e);
4826 }
4827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 int N = pkg.providers.size();
4829 StringBuilder r = null;
4830 int i;
4831 for (i=0; i<N; i++) {
4832 PackageParser.Provider p = pkg.providers.get(i);
4833 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
4834 p.info.processName, pkg.applicationInfo.uid);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004835 mProviders.addProvider(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004837 if (p.info.authority != null) {
4838 String names[] = p.info.authority.split(";");
4839 p.info.authority = null;
4840 for (int j = 0; j < names.length; j++) {
4841 if (j == 1 && p.syncable) {
4842 // We only want the first authority for a provider to possibly be
4843 // syncable, so if we already added this provider using a different
4844 // authority clear the syncable flag. We copy the provider before
4845 // changing it because the mProviders object contains a reference
4846 // to a provider that we don't want to change.
4847 // Only do this for the second authority since the resulting provider
4848 // object can be the same for all future authorities for this provider.
4849 p = new PackageParser.Provider(p);
4850 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004852 if (!mProvidersByAuthority.containsKey(names[j])) {
4853 mProvidersByAuthority.put(names[j], p);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004854 if (p.info.authority == null) {
4855 p.info.authority = names[j];
4856 } else {
4857 p.info.authority = p.info.authority + ";" + names[j];
4858 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004859 if (DEBUG_PACKAGE_SCANNING) {
4860 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4861 Log.d(TAG, "Registered content provider: " + names[j]
4862 + ", className = " + p.info.name + ", isSyncable = "
4863 + p.info.isSyncable);
4864 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004865 } else {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004866 PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004867 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004868 " (in package " + pkg.applicationInfo.packageName +
4869 "): name already used by "
4870 + ((other != null && other.getComponentName() != null)
4871 ? other.getComponentName().getPackageName() : "?"));
4872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 }
4874 }
4875 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4876 if (r == null) {
4877 r = new StringBuilder(256);
4878 } else {
4879 r.append(' ');
4880 }
4881 r.append(p.info.name);
4882 }
4883 }
4884 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004885 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 N = pkg.services.size();
4889 r = null;
4890 for (i=0; i<N; i++) {
4891 PackageParser.Service s = pkg.services.get(i);
4892 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
4893 s.info.processName, pkg.applicationInfo.uid);
4894 mServices.addService(s);
4895 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4896 if (r == null) {
4897 r = new StringBuilder(256);
4898 } else {
4899 r.append(' ');
4900 }
4901 r.append(s.info.name);
4902 }
4903 }
4904 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004905 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 N = pkg.receivers.size();
4909 r = null;
4910 for (i=0; i<N; i++) {
4911 PackageParser.Activity a = pkg.receivers.get(i);
4912 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4913 a.info.processName, pkg.applicationInfo.uid);
4914 mReceivers.addActivity(a, "receiver");
4915 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4916 if (r == null) {
4917 r = new StringBuilder(256);
4918 } else {
4919 r.append(' ');
4920 }
4921 r.append(a.info.name);
4922 }
4923 }
4924 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004925 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 N = pkg.activities.size();
4929 r = null;
4930 for (i=0; i<N; i++) {
4931 PackageParser.Activity a = pkg.activities.get(i);
4932 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4933 a.info.processName, pkg.applicationInfo.uid);
4934 mActivities.addActivity(a, "activity");
4935 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4936 if (r == null) {
4937 r = new StringBuilder(256);
4938 } else {
4939 r.append(' ');
4940 }
4941 r.append(a.info.name);
4942 }
4943 }
4944 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004945 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 N = pkg.permissionGroups.size();
4949 r = null;
4950 for (i=0; i<N; i++) {
4951 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
4952 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
4953 if (cur == null) {
4954 mPermissionGroups.put(pg.info.name, pg);
4955 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4956 if (r == null) {
4957 r = new StringBuilder(256);
4958 } else {
4959 r.append(' ');
4960 }
4961 r.append(pg.info.name);
4962 }
4963 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004964 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 + pg.info.packageName + " ignored: original from "
4966 + cur.info.packageName);
4967 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4968 if (r == null) {
4969 r = new StringBuilder(256);
4970 } else {
4971 r.append(' ');
4972 }
4973 r.append("DUP:");
4974 r.append(pg.info.name);
4975 }
4976 }
4977 }
4978 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004979 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 N = pkg.permissions.size();
4983 r = null;
4984 for (i=0; i<N; i++) {
4985 PackageParser.Permission p = pkg.permissions.get(i);
4986 HashMap<String, BasePermission> permissionMap =
4987 p.tree ? mSettings.mPermissionTrees
4988 : mSettings.mPermissions;
4989 p.group = mPermissionGroups.get(p.info.group);
4990 if (p.info.group == null || p.group != null) {
4991 BasePermission bp = permissionMap.get(p.info.name);
4992 if (bp == null) {
4993 bp = new BasePermission(p.info.name, p.info.packageName,
4994 BasePermission.TYPE_NORMAL);
4995 permissionMap.put(p.info.name, bp);
4996 }
4997 if (bp.perm == null) {
Christopher Tate3aeea1f2013-11-05 12:28:10 -08004998 if (bp.sourcePackage != null
4999 && !bp.sourcePackage.equals(p.info.packageName)) {
5000 // If this is a permission that was formerly defined by a non-system
5001 // app, but is now defined by a system app (following an upgrade),
5002 // discard the previous declaration and consider the system's to be
5003 // canonical.
5004 if (isSystemApp(p.owner)) {
5005 Slog.i(TAG, "New decl " + p.owner + " of permission "
5006 + p.info.name + " is system");
5007 bp.sourcePackage = null;
5008 }
5009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005010 if (bp.sourcePackage == null
5011 || bp.sourcePackage.equals(p.info.packageName)) {
5012 BasePermission tree = findPermissionTreeLP(p.info.name);
5013 if (tree == null
5014 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005015 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 bp.perm = p;
5017 bp.uid = pkg.applicationInfo.uid;
5018 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
5019 if (r == null) {
5020 r = new StringBuilder(256);
5021 } else {
5022 r.append(' ');
5023 }
5024 r.append(p.info.name);
5025 }
5026 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005027 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 + p.info.packageName + " ignored: base tree "
5029 + tree.name + " is from package "
5030 + tree.sourcePackage);
5031 }
5032 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005033 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 + p.info.packageName + " ignored: original from "
5035 + bp.sourcePackage);
5036 }
5037 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
5038 if (r == null) {
5039 r = new StringBuilder(256);
5040 } else {
5041 r.append(' ');
5042 }
5043 r.append("DUP:");
5044 r.append(p.info.name);
5045 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005046 if (bp.perm == p) {
5047 bp.protectionLevel = p.info.protectionLevel;
5048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005050 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 + p.info.packageName + " ignored: no group "
5052 + p.group);
5053 }
5054 }
5055 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08005056 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 N = pkg.instrumentation.size();
5060 r = null;
5061 for (i=0; i<N; i++) {
5062 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
5063 a.info.packageName = pkg.applicationInfo.packageName;
5064 a.info.sourceDir = pkg.applicationInfo.sourceDir;
5065 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
5066 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07005067 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005068 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
5070 if (r == null) {
5071 r = new StringBuilder(256);
5072 } else {
5073 r.append(' ');
5074 }
5075 r.append(a.info.name);
5076 }
5077 }
5078 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08005079 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005081
Dianne Hackborn854060af2009-07-09 18:14:31 -07005082 if (pkg.protectedBroadcasts != null) {
5083 N = pkg.protectedBroadcasts.size();
5084 for (i=0; i<N; i++) {
5085 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
5086 }
5087 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 pkgSetting.setTimeStamp(scanFileTime);
5090 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 return pkg;
5093 }
5094
Jose Limabb9682e2013-08-16 16:14:32 -07005095 private void setUpCustomResolverActivity(PackageParser.Package pkg) {
5096 synchronized (mPackages) {
5097 mResolverReplaced = true;
5098 // Set up information for custom user intent resolution activity.
5099 mResolveActivity.applicationInfo = pkg.applicationInfo;
5100 mResolveActivity.name = mCustomResolverComponentName.getClassName();
5101 mResolveActivity.packageName = pkg.applicationInfo.packageName;
5102 mResolveActivity.processName = null;
5103 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
5104 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
5105 ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
5106 mResolveActivity.theme = 0;
5107 mResolveActivity.exported = true;
5108 mResolveActivity.enabled = true;
5109 mResolveInfo.activityInfo = mResolveActivity;
5110 mResolveInfo.priority = 0;
5111 mResolveInfo.preferredOrder = 0;
5112 mResolveInfo.match = 0;
5113 mResolveComponentName = mCustomResolverComponentName;
5114 Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " +
5115 mResolveComponentName);
5116 }
5117 }
5118
Kenny Rootddbe50d2012-09-06 13:18:37 -07005119 private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
5120 PackageSetting pkgSetting) {
5121 final String apkLibPath = getApkName(pkgSetting.codePathString);
5122 final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
5123 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
5124 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
5125 }
5126
5127 private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
5128 throws IOException {
5129 if (!nativeLibraryDir.isDirectory()) {
5130 nativeLibraryDir.delete();
Kenny Root9bbd70a2012-09-10 11:13:36 -07005131
Kenny Rootddbe50d2012-09-06 13:18:37 -07005132 if (!nativeLibraryDir.mkdir()) {
5133 throw new IOException("Cannot create " + nativeLibraryDir.getPath());
5134 }
Kenny Root9bbd70a2012-09-10 11:13:36 -07005135
Kenny Rootddbe50d2012-09-06 13:18:37 -07005136 try {
5137 Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
5138 | S_IXOTH);
5139 } catch (ErrnoException e) {
5140 throw new IOException("Cannot chmod native library directory "
5141 + nativeLibraryDir.getPath(), e);
5142 }
Kenny Root9bbd70a2012-09-10 11:13:36 -07005143 } else if (!SELinux.restorecon(nativeLibraryDir)) {
5144 throw new IOException("Cannot set SELinux context for " + nativeLibraryDir.getPath());
Kenny Rootddbe50d2012-09-06 13:18:37 -07005145 }
5146
5147 /*
5148 * If this is an internal application or our nativeLibraryPath points to
5149 * the app-lib directory, unpack the libraries if necessary.
5150 */
5151 return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
5152 }
5153
Dianne Hackborn21d9b562013-05-28 17:46:59 -07005154 private void killApplication(String pkgName, int appId, String reason) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005155 // Request the ActivityManager to kill the process(only for existing packages)
5156 // so that we do not end up in a confused state while the user is still using the older
5157 // version of the application while the new one gets installed.
5158 IActivityManager am = ActivityManagerNative.getDefault();
5159 if (am != null) {
5160 try {
Dianne Hackborn21d9b562013-05-28 17:46:59 -07005161 am.killApplicationWithAppId(pkgName, appId, reason);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005162 } catch (RemoteException e) {
5163 }
5164 }
5165 }
5166
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005167 void removePackageLI(PackageSetting ps, boolean chatty) {
5168 if (DEBUG_INSTALL) {
5169 if (chatty)
5170 Log.d(TAG, "Removing package " + ps.name);
5171 }
5172
5173 // writer
5174 synchronized (mPackages) {
5175 mPackages.remove(ps.name);
5176 if (ps.codePathString != null) {
5177 mAppDirs.remove(ps.codePathString);
5178 }
5179
5180 final PackageParser.Package pkg = ps.pkg;
5181 if (pkg != null) {
5182 cleanPackageDataStructuresLILPw(pkg, chatty);
5183 }
5184 }
5185 }
5186
5187 void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08005188 if (DEBUG_INSTALL) {
5189 if (chatty)
5190 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
5191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192
Kenny Root447106f2011-03-23 11:00:15 -07005193 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 mPackages.remove(pkg.applicationInfo.packageName);
5196 if (pkg.mPath != null) {
5197 mAppDirs.remove(pkg.mPath);
5198 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005199 cleanPackageDataStructuresLILPw(pkg, chatty);
5200 }
5201 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005202
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005203 void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
5204 int N = pkg.providers.size();
5205 StringBuilder r = null;
5206 int i;
5207 for (i=0; i<N; i++) {
5208 PackageParser.Provider p = pkg.providers.get(i);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005209 mProviders.removeProvider(p);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005210 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005211
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005212 /* There was another ContentProvider with this authority when
5213 * this app was installed so this authority is null,
5214 * Ignore it as we don't have to unregister the provider.
5215 */
5216 continue;
5217 }
5218 String names[] = p.info.authority.split(";");
5219 for (int j = 0; j < names.length; j++) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005220 if (mProvidersByAuthority.get(names[j]) == p) {
5221 mProvidersByAuthority.remove(names[j]);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005222 if (DEBUG_REMOVE) {
5223 if (chatty)
5224 Log.d(TAG, "Unregistered content provider: " + names[j]
5225 + ", className = " + p.info.name + ", isSyncable = "
5226 + p.info.isSyncable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 }
5228 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005229 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07005230 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005231 if (r == null) {
5232 r = new StringBuilder(256);
5233 } else {
5234 r.append(' ');
5235 }
5236 r.append(p.info.name);
5237 }
5238 }
5239 if (r != null) {
5240 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
5241 }
5242
5243 N = pkg.services.size();
5244 r = null;
5245 for (i=0; i<N; i++) {
5246 PackageParser.Service s = pkg.services.get(i);
5247 mServices.removeService(s);
5248 if (chatty) {
5249 if (r == null) {
5250 r = new StringBuilder(256);
5251 } else {
5252 r.append(' ');
5253 }
5254 r.append(s.info.name);
5255 }
5256 }
5257 if (r != null) {
5258 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
5259 }
5260
5261 N = pkg.receivers.size();
5262 r = null;
5263 for (i=0; i<N; i++) {
5264 PackageParser.Activity a = pkg.receivers.get(i);
5265 mReceivers.removeActivity(a, "receiver");
Dianne Hackbornc895be72013-03-11 17:48:43 -07005266 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005267 if (r == null) {
5268 r = new StringBuilder(256);
5269 } else {
5270 r.append(' ');
5271 }
5272 r.append(a.info.name);
5273 }
5274 }
5275 if (r != null) {
5276 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
5277 }
5278
5279 N = pkg.activities.size();
5280 r = null;
5281 for (i=0; i<N; i++) {
5282 PackageParser.Activity a = pkg.activities.get(i);
5283 mActivities.removeActivity(a, "activity");
Dianne Hackbornc895be72013-03-11 17:48:43 -07005284 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005285 if (r == null) {
5286 r = new StringBuilder(256);
5287 } else {
5288 r.append(' ');
5289 }
5290 r.append(a.info.name);
5291 }
5292 }
5293 if (r != null) {
5294 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
5295 }
5296
5297 N = pkg.permissions.size();
5298 r = null;
5299 for (i=0; i<N; i++) {
5300 PackageParser.Permission p = pkg.permissions.get(i);
5301 BasePermission bp = mSettings.mPermissions.get(p.info.name);
5302 if (bp == null) {
5303 bp = mSettings.mPermissionTrees.get(p.info.name);
5304 }
5305 if (bp != null && bp.perm == p) {
5306 bp.perm = null;
Dianne Hackbornc895be72013-03-11 17:48:43 -07005307 if (DEBUG_REMOVE && chatty) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 if (r == null) {
5309 r = new StringBuilder(256);
5310 } else {
5311 r.append(' ');
5312 }
5313 r.append(p.info.name);
5314 }
5315 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005316 }
5317 if (r != null) {
5318 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
5319 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005320
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005321 N = pkg.instrumentation.size();
5322 r = null;
5323 for (i=0; i<N; i++) {
5324 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
5325 mInstrumentation.remove(a.getComponentName());
Dianne Hackbornc895be72013-03-11 17:48:43 -07005326 if (DEBUG_REMOVE && chatty) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005327 if (r == null) {
5328 r = new StringBuilder(256);
5329 } else {
5330 r.append(' ');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005332 r.append(a.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005334 }
5335 if (r != null) {
5336 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07005338
5339 r = null;
5340 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5341 // Only system apps can hold shared libraries.
5342 if (pkg.libraryNames != null) {
5343 for (i=0; i<pkg.libraryNames.size(); i++) {
5344 String name = pkg.libraryNames.get(i);
5345 SharedLibraryEntry cur = mSharedLibraries.get(name);
5346 if (cur != null && cur.apk != null && cur.apk.equals(pkg.packageName)) {
5347 mSharedLibraries.remove(name);
5348 if (DEBUG_REMOVE && chatty) {
5349 if (r == null) {
5350 r = new StringBuilder(256);
5351 } else {
5352 r.append(' ');
5353 }
5354 r.append(name);
5355 }
5356 }
5357 }
5358 }
5359 }
5360 if (r != null) {
5361 if (DEBUG_REMOVE) Log.d(TAG, " Libraries: " + r);
5362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 }
5364
5365 private static final boolean isPackageFilename(String name) {
5366 return name != null && name.endsWith(".apk");
5367 }
5368
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005369 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
5370 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
5371 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
5372 return true;
5373 }
5374 }
5375 return false;
5376 }
Dianne Hackborne639da72012-02-21 15:11:13 -08005377
5378 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
5379 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
5380 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
5381
Kenny Root447106f2011-03-23 11:00:15 -07005382 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborne639da72012-02-21 15:11:13 -08005383 PackageParser.Package pkgInfo, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07005385 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07005387 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005388 if (bp.packageSetting == null) {
5389 // We may not yet have parsed the package, so just see if
5390 // we still know about its settings.
5391 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
5392 }
5393 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005394 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 + " from package " + bp.sourcePackage);
5396 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005397 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
5398 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
5399 Slog.i(TAG, "Removing old permission tree: " + bp.name
5400 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08005401 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005402 it.remove();
5403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 }
5405 }
5406
5407 // Make sure all dynamic permissions have been assigned to a package,
5408 // and make sure there are no dangling permissions.
5409 it = mSettings.mPermissions.values().iterator();
5410 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07005411 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 if (bp.type == BasePermission.TYPE_DYNAMIC) {
5413 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
5414 + bp.name + " pkg=" + bp.sourcePackage
5415 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005416 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005417 final BasePermission tree = findPermissionTreeLP(bp.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07005418 if (tree != null && tree.perm != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005419 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 bp.perm = new PackageParser.Permission(tree.perm.owner,
5421 new PermissionInfo(bp.pendingInfo));
5422 bp.perm.info.packageName = tree.perm.info.packageName;
5423 bp.perm.info.name = bp.name;
5424 bp.uid = tree.uid;
5425 }
5426 }
5427 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005428 if (bp.packageSetting == null) {
5429 // We may not yet have parsed the package, so just see if
5430 // we still know about its settings.
5431 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
5432 }
5433 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005434 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005435 + " from package " + bp.sourcePackage);
5436 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005437 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
5438 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
5439 Slog.i(TAG, "Removing old permission: " + bp.name
5440 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08005441 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005442 it.remove();
5443 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005444 }
5445 }
5446
5447 // Now update the permissions for all packages, in particular
5448 // replace the granted permissions of the system packages.
Dianne Hackborne639da72012-02-21 15:11:13 -08005449 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005450 for (PackageParser.Package pkg : mPackages.values()) {
5451 if (pkg != pkgInfo) {
Dianne Hackborne639da72012-02-21 15:11:13 -08005452 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005453 }
5454 }
5455 }
5456
5457 if (pkgInfo != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08005458 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 }
5460 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005461
Kenny Root447106f2011-03-23 11:00:15 -07005462 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
5463 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 if (ps == null) {
5465 return;
5466 }
5467 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08005468 HashSet<String> origPermissions = gp.grantedPermissions;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005469 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 if (replace) {
5472 ps.permissionsFixed = false;
5473 if (gp == ps) {
Dianne Hackborne639da72012-02-21 15:11:13 -08005474 origPermissions = new HashSet<String>(gp.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 gp.grantedPermissions.clear();
5476 gp.gids = mGlobalGids;
5477 }
5478 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 if (gp.gids == null) {
5481 gp.gids = mGlobalGids;
5482 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484 final int N = pkg.requestedPermissions.size();
5485 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07005486 final String name = pkg.requestedPermissions.get(i);
Nick Kralevich1cd6c6e2013-03-18 12:56:33 -07005487 final boolean required = pkg.requestedPermissionsRequired.get(i);
Kenny Root447106f2011-03-23 11:00:15 -07005488 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08005489 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08005491 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 }
5493 }
Nick Kralevichdaae5412013-04-01 13:12:26 -07005494
5495 if (bp == null || bp.packageSetting == null) {
5496 Slog.w(TAG, "Unknown permission " + name
5497 + " in package " + pkg.packageName);
5498 continue;
5499 }
5500
5501 final String perm = bp.name;
5502 boolean allowed;
5503 boolean allowedSig = false;
5504 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
5505 if (level == PermissionInfo.PROTECTION_NORMAL
5506 || level == PermissionInfo.PROTECTION_DANGEROUS) {
Nick Kralevich60792852013-04-03 14:12:24 -07005507 // We grant a normal or dangerous permission if any of the following
5508 // are true:
5509 // 1) The permission is required
5510 // 2) The permission is optional, but was granted in the past
5511 // 3) The permission is optional, but was requested by an
5512 // app in /system (not /data)
5513 //
5514 // Otherwise, reject the permission.
5515 allowed = (required || origPermissions.contains(perm)
5516 || (isSystemApp(ps) && !isUpdatedSystemApp(ps)));
Nick Kralevichdaae5412013-04-01 13:12:26 -07005517 } else if (bp.packageSetting == null) {
5518 // This permission is invalid; skip it.
5519 allowed = false;
5520 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
Nick Kralevich94b8c932013-04-02 09:27:27 -07005521 allowed = grantSignaturePermission(perm, pkg, bp, origPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 if (allowed) {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005523 allowedSig = true;
5524 }
5525 } else {
5526 allowed = false;
5527 }
5528 if (DEBUG_INSTALL) {
5529 if (gp != ps) {
5530 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
5531 }
5532 }
5533 if (allowed) {
Nick Kralevich60792852013-04-03 14:12:24 -07005534 if (!isSystemApp(ps) && ps.permissionsFixed) {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005535 // If this is an existing, non-system package, then
5536 // we can't add any new permissions to it.
5537 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005538 // Except... if this is a permission that was added
5539 // to the platform (note: need to only do this when
5540 // updating the platform).
Nick Kralevich3337dbf2013-04-01 13:27:30 -07005541 allowed = isNewPlatformPermissionForPackage(perm, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 }
Nick Kralevichdaae5412013-04-01 13:12:26 -07005543 }
5544 if (allowed) {
5545 if (!gp.grantedPermissions.contains(perm)) {
5546 changedPermission = true;
5547 gp.grantedPermissions.add(perm);
5548 gp.gids = appendInts(gp.gids, bp.gids);
5549 } else if (!ps.haveGids) {
5550 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 }
5552 } else {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005553 Slog.w(TAG, "Not granting permission " + perm
5554 + " to package " + pkg.packageName
5555 + " because it was previously installed without");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 }
5557 } else {
Nick Kralevichdaae5412013-04-01 13:12:26 -07005558 if (gp.grantedPermissions.remove(perm)) {
5559 changedPermission = true;
5560 gp.gids = removeInts(gp.gids, bp.gids);
5561 Slog.i(TAG, "Un-granting permission " + perm
5562 + " from package " + pkg.packageName
5563 + " (protectionLevel=" + bp.protectionLevel
5564 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
5565 + ")");
5566 } else {
5567 Slog.w(TAG, "Not granting permission " + perm
5568 + " to package " + pkg.packageName
5569 + " (protectionLevel=" + bp.protectionLevel
5570 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
5571 + ")");
5572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 }
5574 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005575
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005576 if ((changedPermission || replace) && !ps.permissionsFixed &&
Nick Kralevich60792852013-04-03 14:12:24 -07005577 !isSystemApp(ps) || isUpdatedSystemApp(ps)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 // This is the first that we have heard about this package, so the
5579 // permissions we have now selected are fixed until explicitly
5580 // changed.
5581 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07005583 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005584 }
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005585
Nick Kralevich3337dbf2013-04-01 13:27:30 -07005586 private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
5587 boolean allowed = false;
5588 final int NP = PackageParser.NEW_PERMISSIONS.length;
5589 for (int ip=0; ip<NP; ip++) {
5590 final PackageParser.NewPermissionInfo npi
5591 = PackageParser.NEW_PERMISSIONS[ip];
5592 if (npi.name.equals(perm)
5593 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
5594 allowed = true;
5595 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
5596 + pkg.packageName);
5597 break;
5598 }
5599 }
5600 return allowed;
5601 }
5602
Nick Kralevich94b8c932013-04-02 09:27:27 -07005603 private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005604 BasePermission bp, HashSet<String> origPermissions) {
5605 boolean allowed;
5606 allowed = (compareSignatures(
5607 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
5608 == PackageManager.SIGNATURE_MATCH)
5609 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
5610 == PackageManager.SIGNATURE_MATCH);
5611 if (!allowed && (bp.protectionLevel
5612 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
Christopher Tate072252c2013-07-29 14:20:15 -07005613 if (isSystemApp(pkg)) {
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005614 // For updated system applications, a system permission
5615 // is granted only if it had been defined by the original application.
5616 if (isUpdatedSystemApp(pkg)) {
5617 final PackageSetting sysPs = mSettings
5618 .getDisabledSystemPkgLPr(pkg.packageName);
5619 final GrantedPermissions origGp = sysPs.sharedUser != null
5620 ? sysPs.sharedUser : sysPs;
Christopher Tate072252c2013-07-29 14:20:15 -07005621
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005622 if (origGp.grantedPermissions.contains(perm)) {
Christopher Tate072252c2013-07-29 14:20:15 -07005623 // If the original was granted this permission, we take
5624 // that grant decision as read and propagate it to the
5625 // update.
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005626 allowed = true;
5627 } else {
5628 // The system apk may have been updated with an older
5629 // version of the one on the data partition, but which
5630 // granted a new system permission that it didn't have
5631 // before. In this case we do want to allow the app to
Christopher Tate628946a2013-10-18 18:11:05 -07005632 // now get the new permission if the ancestral apk is
5633 // privileged to get it.
5634 if (sysPs.pkg != null && sysPs.isPrivileged()) {
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005635 for (int j=0;
5636 j<sysPs.pkg.requestedPermissions.size(); j++) {
5637 if (perm.equals(
5638 sysPs.pkg.requestedPermissions.get(j))) {
5639 allowed = true;
5640 break;
5641 }
5642 }
5643 }
5644 }
5645 } else {
Christopher Tate072252c2013-07-29 14:20:15 -07005646 allowed = isPrivilegedApp(pkg);
Nick Kralevich35bee33d2013-04-01 13:08:00 -07005647 }
5648 }
5649 }
5650 if (!allowed && (bp.protectionLevel
5651 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
5652 // For development permissions, a development permission
5653 // is granted only if it was already granted.
5654 allowed = origPermissions.contains(perm);
5655 }
5656 return allowed;
5657 }
5658
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08005659 final class ActivityIntentResolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005660 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07005661 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005662 boolean defaultOnly, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005663 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005664 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005665 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 }
5667
Amith Yamasani483f3b02012-03-13 16:08:00 -07005668 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
5669 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005670 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02005672 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005673 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 }
5675
Kenny Root60f7ad82011-03-22 12:49:06 -07005676 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005677 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005678 if (!sUserManager.exists(userId)) return null;
Mihai Predaeae850c2009-05-13 10:13:48 +02005679 if (packageActivities == null) {
5680 return null;
5681 }
5682 mFlags = flags;
5683 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08005684 final int N = packageActivities.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005685 ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
5686 new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02005687
5688 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02005689 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02005690 intentFilters = packageActivities.get(i).intents;
5691 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005692 PackageParser.ActivityIntentInfo[] array =
5693 new PackageParser.ActivityIntentInfo[intentFilters.size()];
5694 intentFilters.toArray(array);
5695 listCut.add(array);
Mihai Predac3320db2009-05-18 20:15:32 +02005696 }
Mihai Predaeae850c2009-05-13 10:13:48 +02005697 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07005698 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02005699 }
5700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08005702 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005703 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08005704 if (DEBUG_SHOW_INFO)
5705 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 TAG, " " + type + " " +
5707 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005708 if (DEBUG_SHOW_INFO)
5709 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08005710 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02005711 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08005713 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
5714 intent.setPriority(0);
5715 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
5716 + a.className + " with priority > 0, forcing to 0");
5717 }
Kenny Root9718cf52011-02-23 16:45:26 -08005718 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 Log.v(TAG, " IntentFilter:");
5720 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5721 }
5722 if (!intent.debugCheck()) {
5723 Log.w(TAG, "==> For Activity " + a.info.name);
5724 }
5725 addFilter(intent);
5726 }
5727 }
5728
5729 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005730 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08005731 if (DEBUG_SHOW_INFO) {
5732 Log.v(TAG, " " + type + " "
5733 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
5734 : a.info.name) + ":");
5735 Log.v(TAG, " Class=" + a.info.name);
5736 }
5737 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02005738 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005739 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005740 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 Log.v(TAG, " IntentFilter:");
5742 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5743 }
5744 removeFilter(intent);
5745 }
5746 }
5747
5748 @Override
5749 protected boolean allowFilterResult(
5750 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
5751 ActivityInfo filterAi = filter.activity.info;
5752 for (int i=dest.size()-1; i>=0; i--) {
5753 ActivityInfo destAi = dest.get(i).activityInfo;
5754 if (destAi.name == filterAi.name
5755 && destAi.packageName == filterAi.packageName) {
5756 return false;
5757 }
5758 }
5759 return true;
5760 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005763 protected ActivityIntentInfo[] newArray(int size) {
5764 return new ActivityIntentInfo[size];
5765 }
5766
5767 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005768 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005769 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005770 PackageParser.Package p = filter.activity.owner;
5771 if (p != null) {
5772 PackageSetting ps = (PackageSetting)p.mExtras;
5773 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005774 // System apps are never considered stopped for purposes of
5775 // filtering, because there may be no way for the user to
5776 // actually re-launch them.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005777 return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
5778 && ps.getStopped(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005779 }
5780 }
5781 return false;
5782 }
5783
5784 @Override
Ben Gruver4efe9402013-04-02 21:18:41 -07005785 protected boolean isPackageForFilter(String packageName,
5786 PackageParser.ActivityIntentInfo info) {
5787 return packageName.equals(info.activity.owner.packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005788 }
5789
5790 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005792 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005793 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005794 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 return null;
5796 }
5797 final PackageParser.Activity activity = info.activity;
5798 if (mSafeMode && (activity.info.applicationInfo.flags
5799 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5800 return null;
5801 }
Amith Yamasani13593602012-03-22 16:16:17 -07005802 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005803 if (ps == null) {
5804 return null;
5805 }
5806 ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
5807 ps.readUserState(userId), userId);
5808 if (ai == null) {
5809 return null;
5810 }
5811 final ResolveInfo res = new ResolveInfo();
5812 res.activityInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
5814 res.filter = info;
5815 }
5816 res.priority = info.getPriority();
5817 res.preferredOrder = activity.owner.mPreferredOrder;
5818 //System.out.println("Result: " + res.activityInfo.className +
5819 // " = " + res.priority);
5820 res.match = match;
5821 res.isDefault = info.hasDefault;
5822 res.labelRes = info.labelRes;
5823 res.nonLocalizedLabel = info.nonLocalizedLabel;
5824 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005825 res.system = isSystemApp(res.activityInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 return res;
5827 }
5828
5829 @Override
5830 protected void sortResults(List<ResolveInfo> results) {
5831 Collections.sort(results, mResolvePrioritySorter);
5832 }
5833
5834 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005835 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005836 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005837 out.print(prefix); out.print(
5838 Integer.toHexString(System.identityHashCode(filter.activity)));
5839 out.print(' ');
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005840 filter.activity.printComponentShortName(out);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005841 out.print(" filter ");
5842 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 }
5844
5845// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
5846// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
5847// final List<ResolveInfo> retList = Lists.newArrayList();
5848// while (i.hasNext()) {
5849// final ResolveInfo resolveInfo = i.next();
5850// if (isEnabledLP(resolveInfo.activityInfo)) {
5851// retList.add(resolveInfo);
5852// }
5853// }
5854// return retList;
5855// }
5856
5857 // Keys are String (activity class name), values are Activity.
5858 private final HashMap<ComponentName, PackageParser.Activity> mActivities
5859 = new HashMap<ComponentName, PackageParser.Activity>();
5860 private int mFlags;
5861 }
5862
5863 private final class ServiceIntentResolver
5864 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07005865 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005866 boolean defaultOnly, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005868 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 }
5870
Amith Yamasani483f3b02012-03-13 16:08:00 -07005871 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
5872 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005873 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02005875 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005876 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 }
5878
Kenny Root60f7ad82011-03-22 12:49:06 -07005879 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005880 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005881 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005882 if (packageServices == null) {
5883 return null;
5884 }
5885 mFlags = flags;
5886 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08005887 final int N = packageServices.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005888 ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
5889 new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005890
5891 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
5892 for (int i = 0; i < N; ++i) {
5893 intentFilters = packageServices.get(i).intents;
5894 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005895 PackageParser.ServiceIntentInfo[] array =
5896 new PackageParser.ServiceIntentInfo[intentFilters.size()];
5897 intentFilters.toArray(array);
5898 listCut.add(array);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005899 }
5900 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07005901 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005902 }
5903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005905 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08005906 if (DEBUG_SHOW_INFO) {
5907 Log.v(TAG, " "
5908 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005910 Log.v(TAG, " Class=" + s.info.name);
5911 }
5912 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 int j;
5914 for (j=0; j<NI; j++) {
5915 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005916 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 Log.v(TAG, " IntentFilter:");
5918 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5919 }
5920 if (!intent.debugCheck()) {
5921 Log.w(TAG, "==> For Service " + s.info.name);
5922 }
5923 addFilter(intent);
5924 }
5925 }
5926
5927 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005928 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08005929 if (DEBUG_SHOW_INFO) {
5930 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005932 Log.v(TAG, " Class=" + s.info.name);
5933 }
5934 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 int j;
5936 for (j=0; j<NI; j++) {
5937 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005938 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 Log.v(TAG, " IntentFilter:");
5940 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5941 }
5942 removeFilter(intent);
5943 }
5944 }
5945
5946 @Override
5947 protected boolean allowFilterResult(
5948 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
5949 ServiceInfo filterSi = filter.service.info;
5950 for (int i=dest.size()-1; i>=0; i--) {
5951 ServiceInfo destAi = dest.get(i).serviceInfo;
5952 if (destAi.name == filterSi.name
5953 && destAi.packageName == filterSi.packageName) {
5954 return false;
5955 }
5956 }
5957 return true;
5958 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005961 protected PackageParser.ServiceIntentInfo[] newArray(int size) {
5962 return new PackageParser.ServiceIntentInfo[size];
5963 }
5964
5965 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005966 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005967 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005968 PackageParser.Package p = filter.service.owner;
5969 if (p != null) {
5970 PackageSetting ps = (PackageSetting)p.mExtras;
5971 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005972 // System apps are never considered stopped for purposes of
5973 // filtering, because there may be no way for the user to
5974 // actually re-launch them.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005975 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
5976 && ps.getStopped(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005977 }
5978 }
5979 return false;
5980 }
5981
5982 @Override
Ben Gruver4efe9402013-04-02 21:18:41 -07005983 protected boolean isPackageForFilter(String packageName,
5984 PackageParser.ServiceIntentInfo info) {
5985 return packageName.equals(info.service.owner.packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005986 }
5987
5988 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005990 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005991 if (!sUserManager.exists(userId)) return null;
Jason parksa3cdaa52011-01-13 14:15:43 -06005992 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005993 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 return null;
5995 }
5996 final PackageParser.Service service = info.service;
5997 if (mSafeMode && (service.info.applicationInfo.flags
5998 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5999 return null;
6000 }
Amith Yamasani13593602012-03-22 16:16:17 -07006001 PackageSetting ps = (PackageSetting) service.owner.mExtras;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006002 if (ps == null) {
6003 return null;
6004 }
6005 ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
6006 ps.readUserState(userId), userId);
Dianne Hackborn4428e172012-08-24 17:43:05 -07006007 if (si == null) {
6008 return null;
6009 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006010 final ResolveInfo res = new ResolveInfo();
6011 res.serviceInfo = si;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
6013 res.filter = filter;
6014 }
6015 res.priority = info.getPriority();
6016 res.preferredOrder = service.owner.mPreferredOrder;
6017 //System.out.println("Result: " + res.activityInfo.className +
6018 // " = " + res.priority);
6019 res.match = match;
6020 res.isDefault = info.hasDefault;
6021 res.labelRes = info.labelRes;
6022 res.nonLocalizedLabel = info.nonLocalizedLabel;
6023 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07006024 res.system = isSystemApp(res.serviceInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 return res;
6026 }
6027
6028 @Override
6029 protected void sortResults(List<ResolveInfo> results) {
6030 Collections.sort(results, mResolvePrioritySorter);
6031 }
6032
6033 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006034 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006035 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006036 out.print(prefix); out.print(
6037 Integer.toHexString(System.identityHashCode(filter.service)));
6038 out.print(' ');
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006039 filter.service.printComponentShortName(out);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006040 out.print(" filter ");
6041 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 }
6043
6044// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
6045// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
6046// final List<ResolveInfo> retList = Lists.newArrayList();
6047// while (i.hasNext()) {
6048// final ResolveInfo resolveInfo = (ResolveInfo) i;
6049// if (isEnabledLP(resolveInfo.serviceInfo)) {
6050// retList.add(resolveInfo);
6051// }
6052// }
6053// return retList;
6054// }
6055
6056 // Keys are String (activity class name), values are Activity.
6057 private final HashMap<ComponentName, PackageParser.Service> mServices
6058 = new HashMap<ComponentName, PackageParser.Service>();
6059 private int mFlags;
6060 };
6061
Jeff Sharkey85f5f812013-10-07 10:16:12 -07006062 private final class ProviderIntentResolver
6063 extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
6064 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
6065 boolean defaultOnly, int userId) {
6066 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
6067 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
6068 }
6069
6070 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
6071 int userId) {
6072 if (!sUserManager.exists(userId))
6073 return null;
6074 mFlags = flags;
6075 return super.queryIntent(intent, resolvedType,
6076 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
6077 }
6078
6079 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
6080 int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) {
6081 if (!sUserManager.exists(userId))
6082 return null;
6083 if (packageProviders == null) {
6084 return null;
6085 }
6086 mFlags = flags;
6087 final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
6088 final int N = packageProviders.size();
6089 ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
6090 new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
6091
6092 ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
6093 for (int i = 0; i < N; ++i) {
6094 intentFilters = packageProviders.get(i).intents;
6095 if (intentFilters != null && intentFilters.size() > 0) {
6096 PackageParser.ProviderIntentInfo[] array =
6097 new PackageParser.ProviderIntentInfo[intentFilters.size()];
6098 intentFilters.toArray(array);
6099 listCut.add(array);
6100 }
6101 }
6102 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
6103 }
6104
6105 public final void addProvider(PackageParser.Provider p) {
6106 mProviders.put(p.getComponentName(), p);
6107 if (DEBUG_SHOW_INFO) {
6108 Log.v(TAG, " "
6109 + (p.info.nonLocalizedLabel != null
6110 ? p.info.nonLocalizedLabel : p.info.name) + ":");
6111 Log.v(TAG, " Class=" + p.info.name);
6112 }
6113 final int NI = p.intents.size();
6114 int j;
6115 for (j = 0; j < NI; j++) {
6116 PackageParser.ProviderIntentInfo intent = p.intents.get(j);
6117 if (DEBUG_SHOW_INFO) {
6118 Log.v(TAG, " IntentFilter:");
6119 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
6120 }
6121 if (!intent.debugCheck()) {
6122 Log.w(TAG, "==> For Provider " + p.info.name);
6123 }
6124 addFilter(intent);
6125 }
6126 }
6127
6128 public final void removeProvider(PackageParser.Provider p) {
6129 mProviders.remove(p.getComponentName());
6130 if (DEBUG_SHOW_INFO) {
6131 Log.v(TAG, " " + (p.info.nonLocalizedLabel != null
6132 ? p.info.nonLocalizedLabel : p.info.name) + ":");
6133 Log.v(TAG, " Class=" + p.info.name);
6134 }
6135 final int NI = p.intents.size();
6136 int j;
6137 for (j = 0; j < NI; j++) {
6138 PackageParser.ProviderIntentInfo intent = p.intents.get(j);
6139 if (DEBUG_SHOW_INFO) {
6140 Log.v(TAG, " IntentFilter:");
6141 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
6142 }
6143 removeFilter(intent);
6144 }
6145 }
6146
6147 @Override
6148 protected boolean allowFilterResult(
6149 PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
6150 ProviderInfo filterPi = filter.provider.info;
6151 for (int i = dest.size() - 1; i >= 0; i--) {
6152 ProviderInfo destPi = dest.get(i).providerInfo;
6153 if (destPi.name == filterPi.name
6154 && destPi.packageName == filterPi.packageName) {
6155 return false;
6156 }
6157 }
6158 return true;
6159 }
6160
6161 @Override
6162 protected PackageParser.ProviderIntentInfo[] newArray(int size) {
6163 return new PackageParser.ProviderIntentInfo[size];
6164 }
6165
6166 @Override
6167 protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
6168 if (!sUserManager.exists(userId))
6169 return true;
6170 PackageParser.Package p = filter.provider.owner;
6171 if (p != null) {
6172 PackageSetting ps = (PackageSetting) p.mExtras;
6173 if (ps != null) {
6174 // System apps are never considered stopped for purposes of
6175 // filtering, because there may be no way for the user to
6176 // actually re-launch them.
6177 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
6178 && ps.getStopped(userId);
6179 }
6180 }
6181 return false;
6182 }
6183
6184 @Override
6185 protected boolean isPackageForFilter(String packageName,
6186 PackageParser.ProviderIntentInfo info) {
6187 return packageName.equals(info.provider.owner.packageName);
6188 }
6189
6190 @Override
6191 protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
6192 int match, int userId) {
6193 if (!sUserManager.exists(userId))
6194 return null;
6195 final PackageParser.ProviderIntentInfo info = filter;
6196 if (!mSettings.isEnabledLPr(info.provider.info, mFlags, userId)) {
6197 return null;
6198 }
6199 final PackageParser.Provider provider = info.provider;
6200 if (mSafeMode && (provider.info.applicationInfo.flags
6201 & ApplicationInfo.FLAG_SYSTEM) == 0) {
6202 return null;
6203 }
6204 PackageSetting ps = (PackageSetting) provider.owner.mExtras;
6205 if (ps == null) {
6206 return null;
6207 }
6208 ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
6209 ps.readUserState(userId), userId);
6210 if (pi == null) {
6211 return null;
6212 }
6213 final ResolveInfo res = new ResolveInfo();
6214 res.providerInfo = pi;
6215 if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
6216 res.filter = filter;
6217 }
6218 res.priority = info.getPriority();
6219 res.preferredOrder = provider.owner.mPreferredOrder;
6220 res.match = match;
6221 res.isDefault = info.hasDefault;
6222 res.labelRes = info.labelRes;
6223 res.nonLocalizedLabel = info.nonLocalizedLabel;
6224 res.icon = info.icon;
6225 res.system = isSystemApp(res.providerInfo.applicationInfo);
6226 return res;
6227 }
6228
6229 @Override
6230 protected void sortResults(List<ResolveInfo> results) {
6231 Collections.sort(results, mResolvePrioritySorter);
6232 }
6233
6234 @Override
6235 protected void dumpFilter(PrintWriter out, String prefix,
6236 PackageParser.ProviderIntentInfo filter) {
6237 out.print(prefix);
6238 out.print(
6239 Integer.toHexString(System.identityHashCode(filter.provider)));
6240 out.print(' ');
6241 filter.provider.printComponentShortName(out);
6242 out.print(" filter ");
6243 out.println(Integer.toHexString(System.identityHashCode(filter)));
6244 }
6245
6246 private final HashMap<ComponentName, PackageParser.Provider> mProviders
6247 = new HashMap<ComponentName, PackageParser.Provider>();
6248 private int mFlags;
6249 };
6250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
6252 new Comparator<ResolveInfo>() {
6253 public int compare(ResolveInfo r1, ResolveInfo r2) {
6254 int v1 = r1.priority;
6255 int v2 = r2.priority;
6256 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
6257 if (v1 != v2) {
6258 return (v1 > v2) ? -1 : 1;
6259 }
6260 v1 = r1.preferredOrder;
6261 v2 = r2.preferredOrder;
6262 if (v1 != v2) {
6263 return (v1 > v2) ? -1 : 1;
6264 }
6265 if (r1.isDefault != r2.isDefault) {
6266 return r1.isDefault ? -1 : 1;
6267 }
6268 v1 = r1.match;
6269 v2 = r2.match;
6270 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
Dianne Hackbornd99b2932011-08-18 14:39:58 -07006271 if (v1 != v2) {
6272 return (v1 > v2) ? -1 : 1;
6273 }
6274 if (r1.system != r2.system) {
6275 return r1.system ? -1 : 1;
6276 }
6277 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 }
6279 };
6280
6281 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
6282 new Comparator<ProviderInfo>() {
6283 public int compare(ProviderInfo p1, ProviderInfo p2) {
6284 final int v1 = p1.initOrder;
6285 final int v2 = p2.initOrder;
6286 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
6287 }
6288 };
6289
Kenny Root447106f2011-03-23 11:00:15 -07006290 static final void sendPackageBroadcast(String action, String pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006291 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
6292 int[] userIds) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 IActivityManager am = ActivityManagerNative.getDefault();
6294 if (am != null) {
6295 try {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006296 if (userIds == null) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07006297 userIds = am.getRunningUserIds();
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006298 }
Amith Yamasani13593602012-03-22 16:16:17 -07006299 for (int id : userIds) {
6300 final Intent intent = new Intent(action,
6301 pkg != null ? Uri.fromParts("package", pkg, null) : null);
6302 if (extras != null) {
6303 intent.putExtras(extras);
6304 }
6305 if (targetPkg != null) {
6306 intent.setPackage(targetPkg);
6307 }
6308 // Modify the UID when posting to other users
6309 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006310 if (uid > 0 && UserHandle.getUserId(uid) != id) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07006311 uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
Amith Yamasani13593602012-03-22 16:16:17 -07006312 intent.putExtra(Intent.EXTRA_UID, uid);
6313 }
Dianne Hackbornc72fc672012-09-20 13:12:03 -07006314 intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
Amith Yamasani13593602012-03-22 16:16:17 -07006315 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006316 if (DEBUG_BROADCASTS) {
6317 RuntimeException here = new RuntimeException("here");
6318 here.fillInStackTrace();
6319 Slog.d(TAG, "Sending to user " + id + ": "
6320 + intent.toShortString(false, true, false, false)
6321 + " " + intent.getExtras(), here);
6322 }
Amith Yamasani13593602012-03-22 16:16:17 -07006323 am.broadcastIntent(null, intent, null, finishedReceiver,
Dianne Hackbornf51f6122013-02-04 18:23:34 -08006324 0, null, null, null, android.app.AppOpsManager.OP_NONE,
6325 finishedReceiver != null, false, id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 } catch (RemoteException ex) {
6328 }
6329 }
6330 }
Kenny Root300c13a2011-01-18 13:04:40 -08006331
6332 /**
6333 * Check if the external storage media is available. This is true if there
6334 * is a mounted external storage medium or if the external storage is
6335 * emulated.
6336 */
6337 private boolean isExternalMediaAvailable() {
6338 return mMediaMounted || Environment.isExternalStorageEmulated();
6339 }
6340
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006341 public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07006342 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006343 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08006344 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006345 // If the external storage is no longer mounted at this point,
6346 // the caller may not have been able to delete all of this
6347 // packages files and can not delete any more. Bail.
6348 return null;
6349 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07006350 final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
6351 if (lastPackage != null) {
6352 pkgs.remove(lastPackage);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006353 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07006354 if (pkgs.size() > 0) {
6355 return pkgs.get(0);
6356 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006357 }
6358 return null;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006361 void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
6362 if (false) {
6363 RuntimeException here = new RuntimeException("here");
6364 here.fillInStackTrace();
6365 Slog.d(TAG, "Schedule cleaning " + packageName + " user=" + userId
6366 + " andCode=" + andCode, here);
6367 }
6368 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE,
6369 userId, andCode ? 1 : 0, packageName));
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006370 }
6371
Jeff Sharkey752cd922012-09-23 16:25:12 -07006372 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07006373 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006374 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08006375 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006376 return;
6377 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07006378 if (mSettings.mPackagesToBeCleaned.isEmpty()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006379 return;
6380 }
6381 }
6382 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
6383 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
6384 IActivityManager am = ActivityManagerNative.getDefault();
6385 if (am != null) {
6386 try {
Jeff Sharkey752cd922012-09-23 16:25:12 -07006387 am.startService(null, intent, null, UserHandle.USER_OWNER);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006388 } catch (RemoteException e) {
6389 }
6390 }
6391 }
6392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 private final class AppDirObserver extends FileObserver {
Christopher Tate409bb362013-07-12 12:29:41 -07006394 public AppDirObserver(String path, int mask, boolean isrom, boolean isPrivileged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006395 super(path, mask);
6396 mRootDir = path;
6397 mIsRom = isrom;
Christopher Tate409bb362013-07-12 12:29:41 -07006398 mIsPrivileged = isPrivileged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 }
6400
6401 public void onEvent(int event, String path) {
6402 String removedPackage = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006403 int removedAppId = -1;
Dianne Hackborn786b4402012-08-27 15:14:02 -07006404 int[] removedUsers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 String addedPackage = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006406 int addedAppId = -1;
Dianne Hackborn786b4402012-08-27 15:14:02 -07006407 int[] addedUsers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006408
Kenny Root447106f2011-03-23 11:00:15 -07006409 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 synchronized (mInstallLock) {
6411 String fullPathStr = null;
6412 File fullPath = null;
6413 if (path != null) {
6414 fullPath = new File(mRootDir, path);
6415 fullPathStr = fullPath.getPath();
6416 }
6417
Kenny Root9718cf52011-02-23 16:45:26 -08006418 if (DEBUG_APP_DIR_OBSERVER)
6419 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420
6421 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08006422 if (DEBUG_APP_DIR_OBSERVER)
6423 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 return;
6425 }
6426
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006427 // Ignore packages that are being installed or
6428 // have just been installed.
6429 if (ignoreCodePath(fullPathStr)) {
6430 return;
6431 }
6432 PackageParser.Package p = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006433 PackageSetting ps = null;
Kenny Root447106f2011-03-23 11:00:15 -07006434 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006435 synchronized (mPackages) {
6436 p = mAppDirs.get(fullPathStr);
Dianne Hackborn786b4402012-08-27 15:14:02 -07006437 if (p != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006438 ps = mSettings.mPackages.get(p.applicationInfo.packageName);
Dianne Hackborn786b4402012-08-27 15:14:02 -07006439 if (ps != null) {
6440 removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
6441 } else {
6442 removedUsers = sUserManager.getUserIds();
6443 }
6444 }
6445 addedUsers = sUserManager.getUserIds();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 if ((event&REMOVE_EVENTS) != 0) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006448 if (ps != null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07006449 if (DEBUG_REMOVE) Slog.d(TAG, "Package disappeared: " + ps);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006450 removePackageLI(ps, true);
6451 removedPackage = ps.name;
6452 removedAppId = ps.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 }
6454 }
6455
6456 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 if (p == null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07006458 if (DEBUG_INSTALL) Slog.d(TAG, "New file appeared: " + fullPath);
Christopher Tate409bb362013-07-12 12:29:41 -07006459 int flags = PackageParser.PARSE_CHATTY | PackageParser.PARSE_MUST_BE_APK;
6460 if (mIsRom) {
6461 flags |= PackageParser.PARSE_IS_SYSTEM
6462 | PackageParser.PARSE_IS_SYSTEM_DIR;
6463 if (mIsPrivileged) {
6464 flags |= PackageParser.PARSE_IS_PRIVILEGED;
6465 }
6466 }
6467 p = scanPackageLI(fullPath, flags,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006468 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
Dianne Hackborn786b4402012-08-27 15:14:02 -07006469 System.currentTimeMillis(), UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07006471 /*
6472 * TODO this seems dangerous as the package may have
6473 * changed since we last acquired the mPackages
6474 * lock.
6475 */
6476 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006478 updatePermissionsLPw(p.packageName, p,
Dianne Hackborne639da72012-02-21 15:11:13 -08006479 p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 }
6481 addedPackage = p.applicationInfo.packageName;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006482 addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 }
6484 }
6485 }
6486
Kenny Root447106f2011-03-23 11:00:15 -07006487 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006489 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 }
6491 }
6492
6493 if (removedPackage != null) {
6494 Bundle extras = new Bundle(1);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006495 extras.putInt(Intent.EXTRA_UID, removedAppId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006497 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborn786b4402012-08-27 15:14:02 -07006498 extras, null, null, removedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006499 }
6500 if (addedPackage != null) {
6501 Bundle extras = new Bundle(1);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07006502 extras.putInt(Intent.EXTRA_UID, addedAppId);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006503 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Dianne Hackborn786b4402012-08-27 15:14:02 -07006504 extras, null, null, addedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 }
6506 }
6507
6508 private final String mRootDir;
6509 private final boolean mIsRom;
Christopher Tate409bb362013-07-12 12:29:41 -07006510 private final boolean mIsPrivileged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006513 /* Called when a downloaded package installation has been confirmed by the user */
6514 public void installPackage(
6515 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02006516 installPackage(packageURI, observer, flags, null);
6517 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006518
Jacek Surazski65e13172009-04-28 15:26:38 +02006519 /* Called when a downloaded package installation has been confirmed by the user */
6520 public void installPackage(
6521 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
6522 final String installerPackageName) {
Kenny Root5ab21572011-07-27 11:11:19 -07006523 installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
Rich Canningse1d7c712012-08-08 12:46:06 -07006524 null, null);
Kenny Root5ab21572011-07-27 11:11:19 -07006525 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006526
Kenny Root5ab21572011-07-27 11:11:19 -07006527 @Override
6528 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
6529 int flags, String installerPackageName, Uri verificationURI,
Rich Canningse1d7c712012-08-08 12:46:06 -07006530 ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
rich cannings706e8ba2012-08-20 13:20:14 -07006531 VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
Ben Gruver37d83a32012-09-27 13:02:06 -07006532 VerificationParams.NO_UID, manifestDigest);
rich cannings706e8ba2012-08-20 13:20:14 -07006533 installPackageWithVerificationAndEncryption(packageURI, observer, flags,
6534 installerPackageName, verificationParams, encryptionParams);
6535 }
6536
6537 public void installPackageWithVerificationAndEncryption(Uri packageURI,
6538 IPackageInstallObserver observer, int flags, String installerPackageName,
6539 VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
6540 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
6541 null);
Kenny Root5ab21572011-07-27 11:11:19 -07006542
6543 final int uid = Binder.getCallingUid();
Amith Yamasani71e6c692013-03-24 17:39:28 -07006544 if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006545 try {
6546 observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
6547 } catch (RemoteException re) {
6548 }
6549 return;
6550 }
6551
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006552 UserHandle user;
6553 if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
6554 user = UserHandle.ALL;
6555 } else {
Dianne Hackborn786b4402012-08-27 15:14:02 -07006556 user = new UserHandle(UserHandle.getUserId(uid));
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006557 }
Kenny Root5ab21572011-07-27 11:11:19 -07006558
6559 final int filteredFlags;
6560
6561 if (uid == Process.SHELL_UID || uid == 0) {
6562 if (DEBUG_INSTALL) {
6563 Slog.v(TAG, "Install from ADB");
6564 }
6565 filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
6566 } else {
6567 filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
6568 }
6569
rich cannings13d428e2012-09-13 13:43:07 -07006570 verificationParams.setInstallerUid(uid);
6571
Kenny Root5ab21572011-07-27 11:11:19 -07006572 final Message msg = mHandler.obtainMessage(INIT_COPY);
6573 msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006574 verificationParams, encryptionParams, user);
Kenny Root5ab21572011-07-27 11:11:19 -07006575 mHandler.sendMessage(msg);
6576 }
6577
Amith Yamasani655d0e22013-06-12 14:19:10 -07006578 private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting, int userId) {
6579 Bundle extras = new Bundle(1);
6580 extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
6581
6582 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
6583 packageName, extras, null, null, new int[] {userId});
6584 try {
6585 IActivityManager am = ActivityManagerNative.getDefault();
6586 final boolean isSystem =
6587 isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
6588 if (isSystem && am.isUserRunning(userId, false)) {
6589 // The just-installed/enabled app is bundled on the system, so presumed
6590 // to be able to run automatically without needing an explicit launch.
6591 // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
6592 Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
6593 .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
6594 .setPackage(packageName);
6595 am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
6596 android.app.AppOpsManager.OP_NONE, false, false, userId);
6597 }
6598 } catch (RemoteException e) {
6599 // shouldn't happen
6600 Slog.w(TAG, "Unable to bootstrap installed package", e);
6601 }
6602 }
6603
6604 @Override
6605 public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
6606 int userId) {
6607 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
6608 PackageSetting pkgSetting;
6609 final int uid = Binder.getCallingUid();
6610 if (UserHandle.getUserId(uid) != userId) {
Amith Yamasani1a7472e2013-07-02 11:17:30 -07006611 mContext.enforceCallingOrSelfPermission(
Amith Yamasani655d0e22013-06-12 14:19:10 -07006612 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
Amith Yamasani1a7472e2013-07-02 11:17:30 -07006613 "setApplicationBlockedSetting for user " + userId);
Amith Yamasani655d0e22013-06-12 14:19:10 -07006614 }
6615
6616 if (blocked && isPackageDeviceAdmin(packageName, userId)) {
6617 Slog.w(TAG, "Not blocking package " + packageName + ": has active device admin");
6618 return false;
6619 }
6620
6621 long callingId = Binder.clearCallingIdentity();
6622 try {
6623 boolean sendAdded = false;
6624 boolean sendRemoved = false;
6625 // writer
6626 synchronized (mPackages) {
6627 pkgSetting = mSettings.mPackages.get(packageName);
6628 if (pkgSetting == null) {
6629 return false;
6630 }
6631 if (pkgSetting.getBlocked(userId) != blocked) {
6632 pkgSetting.setBlocked(blocked, userId);
6633 mSettings.writePackageRestrictionsLPr(userId);
6634 if (blocked) {
6635 sendRemoved = true;
6636 } else {
6637 sendAdded = true;
6638 }
6639 }
6640 }
6641 if (sendAdded) {
6642 sendPackageAddedForUser(packageName, pkgSetting, userId);
6643 return true;
6644 }
6645 if (sendRemoved) {
Amith Yamasani1a7472e2013-07-02 11:17:30 -07006646 killApplication(packageName, UserHandle.getUid(userId, pkgSetting.appId),
6647 "blocking pkg");
Amith Yamasani655d0e22013-06-12 14:19:10 -07006648 sendPackageBlockedForUser(packageName, pkgSetting, userId);
6649 }
6650 } finally {
6651 Binder.restoreCallingIdentity(callingId);
6652 }
6653 return false;
6654 }
6655
6656 private void sendPackageBlockedForUser(String packageName, PackageSetting pkgSetting,
6657 int userId) {
6658 final PackageRemovedInfo info = new PackageRemovedInfo();
6659 info.removedPackage = packageName;
6660 info.removedUsers = new int[] {userId};
6661 info.uid = UserHandle.getUid(userId, pkgSetting.appId);
6662 info.sendBroadcast(false, false, false);
6663 }
6664
6665 /**
6666 * Returns true if application is not found or there was an error. Otherwise it returns
6667 * the blocked state of the package for the given user.
6668 */
6669 @Override
6670 public boolean getApplicationBlockedSettingAsUser(String packageName, int userId) {
6671 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
6672 PackageSetting pkgSetting;
6673 final int uid = Binder.getCallingUid();
6674 if (UserHandle.getUserId(uid) != userId) {
6675 mContext.enforceCallingPermission(
6676 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6677 "getApplicationBlocked for user " + userId);
6678 }
6679 long callingId = Binder.clearCallingIdentity();
6680 try {
6681 // writer
6682 synchronized (mPackages) {
6683 pkgSetting = mSettings.mPackages.get(packageName);
6684 if (pkgSetting == null) {
6685 return true;
6686 }
6687 return pkgSetting.getBlocked(userId);
6688 }
6689 } finally {
6690 Binder.restoreCallingIdentity(callingId);
6691 }
6692 }
6693
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006694 /**
6695 * @hide
6696 */
6697 @Override
Amith Yamasani67df64b2012-12-14 12:09:36 -08006698 public int installExistingPackageAsUser(String packageName, int userId) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006699 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
6700 null);
6701 PackageSetting pkgSetting;
6702 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08006703 if (UserHandle.getUserId(uid) != userId) {
6704 mContext.enforceCallingPermission(
6705 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6706 "installExistingPackage for user " + userId);
6707 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07006708 if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006709 return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
6710 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006711
6712 long callingId = Binder.clearCallingIdentity();
6713 try {
6714 boolean sendAdded = false;
6715 Bundle extras = new Bundle(1);
6716
6717 // writer
6718 synchronized (mPackages) {
6719 pkgSetting = mSettings.mPackages.get(packageName);
6720 if (pkgSetting == null) {
6721 return PackageManager.INSTALL_FAILED_INVALID_URI;
6722 }
6723 if (!pkgSetting.getInstalled(userId)) {
6724 pkgSetting.setInstalled(true, userId);
Amith Yamasani655d0e22013-06-12 14:19:10 -07006725 pkgSetting.setBlocked(false, userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006726 mSettings.writePackageRestrictionsLPr(userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006727 sendAdded = true;
6728 }
6729 }
6730
6731 if (sendAdded) {
Amith Yamasani655d0e22013-06-12 14:19:10 -07006732 sendPackageAddedForUser(packageName, pkgSetting, userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006733 }
6734 } finally {
6735 Binder.restoreCallingIdentity(callingId);
6736 }
6737
6738 return PackageManager.INSTALL_SUCCEEDED;
6739 }
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006740
Amith Yamasani71e6c692013-03-24 17:39:28 -07006741 private boolean isUserRestricted(int userId, String restrictionKey) {
Amith Yamasani67df64b2012-12-14 12:09:36 -08006742 Bundle restrictions = sUserManager.getUserRestrictions(userId);
Amith Yamasani71e6c692013-03-24 17:39:28 -07006743 if (restrictions.getBoolean(restrictionKey, false)) {
6744 Log.w(TAG, "User is restricted: " + restrictionKey);
6745 return true;
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006746 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07006747 return false;
Amith Yamasanie4cf7342012-12-17 11:12:09 -08006748 }
6749
Kenny Root5ab21572011-07-27 11:11:19 -07006750 @Override
Kenny Root05ca4c92011-09-15 10:36:25 -07006751 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
rich cannings7e671512012-08-27 14:44:16 -07006752 mContext.enforceCallingOrSelfPermission(
6753 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6754 "Only package verification agents can verify applications");
6755
Kenny Root5ab21572011-07-27 11:11:19 -07006756 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
Kenny Root05ca4c92011-09-15 10:36:25 -07006757 final PackageVerificationResponse response = new PackageVerificationResponse(
6758 verificationCode, Binder.getCallingUid());
Kenny Root5ab21572011-07-27 11:11:19 -07006759 msg.arg1 = id;
Kenny Root05ca4c92011-09-15 10:36:25 -07006760 msg.obj = response;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006761 mHandler.sendMessage(msg);
6762 }
6763
rich canningsd9ef3e52012-08-22 14:28:05 -07006764 @Override
6765 public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
6766 long millisecondsToDelay) {
rich cannings7e671512012-08-27 14:44:16 -07006767 mContext.enforceCallingOrSelfPermission(
6768 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6769 "Only package verification agents can extend verification timeouts");
6770
rich canningsd9ef3e52012-08-22 14:28:05 -07006771 final PackageVerificationState state = mPendingVerification.get(id);
6772 final PackageVerificationResponse response = new PackageVerificationResponse(
6773 verificationCodeAtTimeout, Binder.getCallingUid());
6774
rich canningsd1b5cfc2012-08-29 14:49:51 -07006775 if (millisecondsToDelay > PackageManager.MAXIMUM_VERIFICATION_TIMEOUT) {
6776 millisecondsToDelay = PackageManager.MAXIMUM_VERIFICATION_TIMEOUT;
6777 }
6778 if (millisecondsToDelay < 0) {
6779 millisecondsToDelay = 0;
rich canningsd9ef3e52012-08-22 14:28:05 -07006780 }
6781 if ((verificationCodeAtTimeout != PackageManager.VERIFICATION_ALLOW)
rich canningsd1b5cfc2012-08-29 14:49:51 -07006782 && (verificationCodeAtTimeout != PackageManager.VERIFICATION_REJECT)) {
6783 verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
rich canningsd9ef3e52012-08-22 14:28:05 -07006784 }
6785
6786 if ((state != null) && !state.timeoutExtended()) {
6787 state.extendTimeout();
6788
6789 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
6790 msg.arg1 = id;
6791 msg.obj = response;
6792 mHandler.sendMessageDelayed(msg, millisecondsToDelay);
6793 }
6794 }
6795
rich canningsd1b5cfc2012-08-29 14:49:51 -07006796 private void broadcastPackageVerified(int verificationId, Uri packageUri,
rich canningsd55deb02012-10-02 14:53:08 -07006797 int verificationCode, UserHandle user) {
rich canningsd1b5cfc2012-08-29 14:49:51 -07006798 final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
6799 intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
6800 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
6801 intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
6802 intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode);
6803
rich canningsd55deb02012-10-02 14:53:08 -07006804 mContext.sendBroadcastAsUser(intent, user,
6805 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
rich canningsd1b5cfc2012-08-29 14:49:51 -07006806 }
6807
Kenny Root05ca4c92011-09-15 10:36:25 -07006808 private ComponentName matchComponentForVerifier(String packageName,
6809 List<ResolveInfo> receivers) {
6810 ActivityInfo targetReceiver = null;
6811
6812 final int NR = receivers.size();
6813 for (int i = 0; i < NR; i++) {
6814 final ResolveInfo info = receivers.get(i);
6815 if (info.activityInfo == null) {
6816 continue;
6817 }
6818
6819 if (packageName.equals(info.activityInfo.packageName)) {
6820 targetReceiver = info.activityInfo;
6821 break;
6822 }
6823 }
6824
6825 if (targetReceiver == null) {
6826 return null;
6827 }
6828
6829 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
6830 }
6831
6832 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
6833 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
6834 if (pkgInfo.verifiers.length == 0) {
6835 return null;
6836 }
6837
6838 final int N = pkgInfo.verifiers.length;
6839 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
6840 for (int i = 0; i < N; i++) {
6841 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
6842
6843 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
6844 receivers);
6845 if (comp == null) {
6846 continue;
6847 }
6848
6849 final int verifierUid = getUidForVerifier(verifierInfo);
6850 if (verifierUid == -1) {
6851 continue;
6852 }
6853
6854 if (DEBUG_VERIFY) {
6855 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
6856 + " with the correct signature");
6857 }
6858 sufficientVerifiers.add(comp);
6859 verificationState.addSufficientVerifier(verifierUid);
6860 }
6861
6862 return sufficientVerifiers;
6863 }
6864
6865 private int getUidForVerifier(VerifierInfo verifierInfo) {
6866 synchronized (mPackages) {
6867 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
6868 if (pkg == null) {
6869 return -1;
6870 } else if (pkg.mSignatures.length != 1) {
6871 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
6872 + " has more than one signature; ignoring");
6873 return -1;
6874 }
6875
6876 /*
6877 * If the public key of the package's signature does not match
6878 * our expected public key, then this is a different package and
6879 * we should skip.
6880 */
6881
6882 final byte[] expectedPublicKey;
6883 try {
6884 final Signature verifierSig = pkg.mSignatures[0];
6885 final PublicKey publicKey = verifierSig.getPublicKey();
6886 expectedPublicKey = publicKey.getEncoded();
6887 } catch (CertificateException e) {
6888 return -1;
6889 }
6890
6891 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
6892
6893 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
6894 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
6895 + " does not have the expected public key; ignoring");
6896 return -1;
6897 }
6898
6899 return pkg.applicationInfo.uid;
6900 }
6901 }
6902
Christopher Tate1bb69062010-02-19 17:02:12 -08006903 public void finishPackageInstall(int token) {
Kenny Root461ff1f2011-08-09 09:43:03 -07006904 enforceSystemOrRoot("Only the system is allowed to finish installs");
6905
6906 if (DEBUG_INSTALL) {
6907 Slog.v(TAG, "BM finishing package install for " + token);
6908 }
6909
6910 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
Christopher Tate1bb69062010-02-19 17:02:12 -08006911 mHandler.sendMessage(msg);
6912 }
6913
Kenny Root5ab21572011-07-27 11:11:19 -07006914 /**
6915 * Get the verification agent timeout.
6916 *
6917 * @return verification timeout in milliseconds
6918 */
6919 private long getVerificationTimeout() {
rich cannings4d8fc792012-09-07 14:43:43 -07006920 return android.provider.Settings.Global.getLong(mContext.getContentResolver(),
6921 android.provider.Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
Kenny Root5ab21572011-07-27 11:11:19 -07006922 DEFAULT_VERIFICATION_TIMEOUT);
6923 }
6924
6925 /**
rich canningsa6cfe522012-05-21 15:50:56 -07006926 * Get the default verification agent response code.
6927 *
6928 * @return default verification response code
6929 */
6930 private int getDefaultVerificationResponse() {
rich cannings4d8fc792012-09-07 14:43:43 -07006931 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
6932 android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
rich canningsa6cfe522012-05-21 15:50:56 -07006933 DEFAULT_VERIFICATION_RESPONSE);
6934 }
6935
6936 /**
Kenny Root5ab21572011-07-27 11:11:19 -07006937 * Check whether or not package verification has been enabled.
6938 *
6939 * @return true if verification should be performed
6940 */
rich cannings4e5753f2012-09-19 16:03:56 -07006941 private boolean isVerificationEnabled(int flags) {
rich canningse4bf0ea2012-09-14 13:18:55 -07006942 if (!DEFAULT_VERIFY_ENABLE) {
6943 return false;
6944 }
6945
rich cannings4e5753f2012-09-19 16:03:56 -07006946 // Check if installing from ADB
6947 if ((flags & PackageManager.INSTALL_FROM_ADB) != 0) {
rich canningsa2064df2012-09-30 14:52:41 -07006948 // Do not run verification in a test harness environment
6949 if (ActivityManager.isRunningInTestHarness()) {
6950 return false;
6951 }
rich cannings4e5753f2012-09-19 16:03:56 -07006952 // Check if the developer does not want package verification for ADB installs
6953 if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
6954 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
6955 return false;
6956 }
6957 }
6958
rich cannings4d8fc792012-09-07 14:43:43 -07006959 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
rich canningse4bf0ea2012-09-14 13:18:55 -07006960 android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
Kenny Root5ab21572011-07-27 11:11:19 -07006961 }
6962
Matt Finifterf8a98ed2012-05-14 15:43:34 -07006963 /**
6964 * Get the "allow unknown sources" setting.
6965 *
6966 * @return the current "allow unknown sources" setting
6967 */
6968 private int getUnknownSourcesSettings() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -07006969 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
6970 android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
Matt Finifterf8a98ed2012-05-14 15:43:34 -07006971 -1);
6972 }
6973
Kenny Rootf03b45f2011-02-23 17:25:45 -08006974 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08006975 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07006976 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08006977 synchronized (mPackages) {
6978 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
6979 if (targetPackageSetting == null) {
6980 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
6981 }
6982
6983 PackageSetting installerPackageSetting;
6984 if (installerPackageName != null) {
6985 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
6986 if (installerPackageSetting == null) {
6987 throw new IllegalArgumentException("Unknown installer package: "
6988 + installerPackageName);
6989 }
6990 } else {
6991 installerPackageSetting = null;
6992 }
6993
6994 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07006995 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08006996 if (obj != null) {
6997 if (obj instanceof SharedUserSetting) {
6998 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
6999 } else if (obj instanceof PackageSetting) {
7000 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
7001 } else {
7002 throw new SecurityException("Bad object " + obj + " for uid " + uid);
7003 }
7004 } else {
7005 throw new SecurityException("Unknown calling uid " + uid);
7006 }
7007
7008 // Verify: can't set installerPackageName to a package that is
7009 // not signed with the same cert as the caller.
7010 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007011 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08007012 installerPackageSetting.signatures.mSignatures)
7013 != PackageManager.SIGNATURE_MATCH) {
7014 throw new SecurityException(
7015 "Caller does not have same cert as new installer package "
7016 + installerPackageName);
7017 }
7018 }
7019
7020 // Verify: if target already has an installer package, it must
7021 // be signed with the same cert as the caller.
7022 if (targetPackageSetting.installerPackageName != null) {
7023 PackageSetting setting = mSettings.mPackages.get(
7024 targetPackageSetting.installerPackageName);
7025 // If the currently set package isn't valid, then it's always
7026 // okay to change it.
7027 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007028 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08007029 setting.signatures.mSignatures)
7030 != PackageManager.SIGNATURE_MATCH) {
7031 throw new SecurityException(
7032 "Caller does not have same cert as old installer package "
7033 + targetPackageSetting.installerPackageName);
7034 }
7035 }
7036 }
7037
7038 // Okay!
7039 targetPackageSetting.installerPackageName = installerPackageName;
7040 scheduleWriteSettingsLocked();
7041 }
7042 }
7043
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007044 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 // Queue up an async operation since the package installation may take a little while.
7046 mHandler.post(new Runnable() {
7047 public void run() {
7048 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007049 // Result object to be returned
7050 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007051 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007052 res.uid = -1;
7053 res.pkg = null;
7054 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007055 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007056 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007057 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007058 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007059 }
Kenny Root6dceb882012-04-12 14:23:49 -07007060 args.doPostInstall(res.returnCode, res.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007061 }
Christopher Tate1bb69062010-02-19 17:02:12 -08007062
7063 // A restore should be performed at this point if (a) the install
7064 // succeeded, (b) the operation is not an update, and (c) the new
7065 // package has a backupAgent defined.
7066 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08007067 boolean doRestore = (!update
7068 && res.pkg != null
7069 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08007070
7071 // Set up the post-install work request bookkeeping. This will be used
7072 // and cleaned up by the post-install event handling regardless of whether
7073 // there's a restore pass performed. Token values are >= 1.
7074 int token;
7075 if (mNextInstallToken < 0) mNextInstallToken = 1;
7076 token = mNextInstallToken++;
7077
7078 PostInstallData data = new PostInstallData(args, res);
7079 mRunningInstalls.put(token, data);
7080 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
7081
7082 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
7083 // Pass responsibility to the Backup Manager. It will perform a
7084 // restore if appropriate, then pass responsibility back to the
7085 // Package Manager to run the post-install observer callbacks
7086 // and broadcasts.
7087 IBackupManager bm = IBackupManager.Stub.asInterface(
7088 ServiceManager.getService(Context.BACKUP_SERVICE));
7089 if (bm != null) {
7090 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
7091 + " to BM for possible restore");
7092 try {
7093 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
7094 } catch (RemoteException e) {
7095 // can't happen; the backup manager is local
7096 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007097 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08007098 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007099 }
Christopher Tate1bb69062010-02-19 17:02:12 -08007100 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007101 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08007102 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007104 }
Christopher Tate1bb69062010-02-19 17:02:12 -08007105
7106 if (!doRestore) {
7107 // No restore possible, or the Backup Manager was mysteriously not
7108 // available -- just fire the post-install work request directly.
7109 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
7110 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
7111 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007113 }
7114 });
7115 }
7116
Kenny Root5ab21572011-07-27 11:11:19 -07007117 private abstract class HandlerParams {
7118 private static final int MAX_RETRIES = 4;
7119
7120 /**
7121 * Number of times startCopy() has been attempted and had a non-fatal
7122 * error.
7123 */
7124 private int mRetries = 0;
7125
Amith Yamasani6ec10122012-08-23 13:49:25 -07007126 /** User handle for the user requesting the information or installation. */
7127 private final UserHandle mUser;
7128
7129 HandlerParams(UserHandle user) {
7130 mUser = user;
7131 }
7132
7133 UserHandle getUser() {
7134 return mUser;
7135 }
7136
Dianne Hackborn7d608422011-08-07 16:24:18 -07007137 final boolean startCopy() {
7138 boolean res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007139 try {
Dianne Hackbornc895be72013-03-11 17:48:43 -07007140 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
Kenny Root5ab21572011-07-27 11:11:19 -07007141
7142 if (++mRetries > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007143 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007144 mHandler.sendEmptyMessage(MCS_GIVE_UP);
7145 handleServiceError();
Dianne Hackborn7d608422011-08-07 16:24:18 -07007146 return false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007147 } else {
7148 handleStartCopy();
Dianne Hackborn7d608422011-08-07 16:24:18 -07007149 res = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007150 }
7151 } catch (RemoteException e) {
Kenny Root5ab21572011-07-27 11:11:19 -07007152 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007153 mHandler.sendEmptyMessage(MCS_RECONNECT);
Dianne Hackborn7d608422011-08-07 16:24:18 -07007154 res = false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007155 }
7156 handleReturnCode();
Dianne Hackborn7d608422011-08-07 16:24:18 -07007157 return res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007158 }
7159
7160 final void serviceError() {
Kenny Root5ab21572011-07-27 11:11:19 -07007161 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007162 handleServiceError();
7163 handleReturnCode();
7164 }
Kenny Root5ab21572011-07-27 11:11:19 -07007165
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007166 abstract void handleStartCopy() throws RemoteException;
7167 abstract void handleServiceError();
7168 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007169 }
7170
Kenny Root366949c2011-01-14 17:18:14 -08007171 class MeasureParams extends HandlerParams {
7172 private final PackageStats mStats;
7173 private boolean mSuccess;
7174
7175 private final IPackageStatsObserver mObserver;
7176
Kenny Roota69b7eb2012-05-14 14:47:06 -07007177 public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
Amith Yamasani6ec10122012-08-23 13:49:25 -07007178 super(new UserHandle(stats.userHandle));
Kenny Root366949c2011-01-14 17:18:14 -08007179 mObserver = observer;
7180 mStats = stats;
Kenny Root366949c2011-01-14 17:18:14 -08007181 }
7182
7183 @Override
Dianne Hackbornc895be72013-03-11 17:48:43 -07007184 public String toString() {
7185 return "MeasureParams{"
7186 + Integer.toHexString(System.identityHashCode(this))
7187 + " " + mStats.packageName + "}";
7188 }
7189
7190 @Override
Kenny Root366949c2011-01-14 17:18:14 -08007191 void handleStartCopy() throws RemoteException {
Kenny Roota69b7eb2012-05-14 14:47:06 -07007192 synchronized (mInstallLock) {
Dianne Hackborn0c380492012-08-20 17:23:30 -07007193 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
Kenny Roota69b7eb2012-05-14 14:47:06 -07007194 }
Kenny Root366949c2011-01-14 17:18:14 -08007195
Kenny Roota69b7eb2012-05-14 14:47:06 -07007196 final boolean mounted;
Kenny Root366949c2011-01-14 17:18:14 -08007197 if (Environment.isExternalStorageEmulated()) {
7198 mounted = true;
7199 } else {
7200 final String status = Environment.getExternalStorageState();
Jeff Sharkeyb049e212012-09-07 23:16:01 -07007201 mounted = (Environment.MEDIA_MOUNTED.equals(status)
7202 || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
Kenny Root366949c2011-01-14 17:18:14 -08007203 }
7204
7205 if (mounted) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07007206 final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
7207
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007208 mStats.externalCacheSize = calculateDirectorySize(mContainerService,
7209 userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
Kenny Root366949c2011-01-14 17:18:14 -08007210
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007211 mStats.externalDataSize = calculateDirectorySize(mContainerService,
7212 userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
Kenny Root366949c2011-01-14 17:18:14 -08007213
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007214 // Always subtract cache size, since it's a subdirectory
7215 mStats.externalDataSize -= mStats.externalCacheSize;
Kenny Root366949c2011-01-14 17:18:14 -08007216
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007217 mStats.externalMediaSize = calculateDirectorySize(mContainerService,
7218 userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
Kenny Rootbcd6c962011-01-17 11:21:49 -08007219
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007220 mStats.externalObbSize = calculateDirectorySize(mContainerService,
7221 userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
Kenny Root366949c2011-01-14 17:18:14 -08007222 }
7223 }
7224
7225 @Override
7226 void handleReturnCode() {
7227 if (mObserver != null) {
7228 try {
7229 mObserver.onGetStatsCompleted(mStats, mSuccess);
7230 } catch (RemoteException e) {
7231 Slog.i(TAG, "Observer no longer exists.");
7232 }
7233 }
7234 }
7235
7236 @Override
7237 void handleServiceError() {
7238 Slog.e(TAG, "Could not measure application " + mStats.packageName
7239 + " external storage");
7240 }
7241 }
7242
Jeff Sharkey1abdb712013-08-11 16:28:14 -07007243 private static long calculateDirectorySize(IMediaContainerService mcs, File[] paths)
7244 throws RemoteException {
7245 long result = 0;
7246 for (File path : paths) {
7247 result += mcs.calculateDirectorySize(path.getAbsolutePath());
7248 }
7249 return result;
7250 }
7251
7252 private static void clearDirectory(IMediaContainerService mcs, File[] paths) {
7253 for (File path : paths) {
7254 try {
7255 mcs.clearDirectory(path.getAbsolutePath());
7256 } catch (RemoteException e) {
7257 }
7258 }
7259 }
7260
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007261 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007262 final IPackageInstallObserver observer;
7263 int flags;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007264
7265 private final Uri mPackageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007266 final String installerPackageName;
rich cannings706e8ba2012-08-20 13:20:14 -07007267 final VerificationParams verificationParams;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007268 private InstallArgs mArgs;
7269 private int mRet;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007270 private File mTempPackage;
7271 final ContainerEncryptionParams encryptionParams;
Kenny Root5ab21572011-07-27 11:11:19 -07007272
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007273 InstallParams(Uri packageURI,
7274 IPackageInstallObserver observer, int flags,
rich cannings706e8ba2012-08-20 13:20:14 -07007275 String installerPackageName, VerificationParams verificationParams,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007276 ContainerEncryptionParams encryptionParams, UserHandle user) {
Amith Yamasani6ec10122012-08-23 13:49:25 -07007277 super(user);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007278 this.mPackageURI = packageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007279 this.flags = flags;
7280 this.observer = observer;
7281 this.installerPackageName = installerPackageName;
rich cannings706e8ba2012-08-20 13:20:14 -07007282 this.verificationParams = verificationParams;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007283 this.encryptionParams = encryptionParams;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007284 }
7285
Dianne Hackbornc895be72013-03-11 17:48:43 -07007286 @Override
7287 public String toString() {
7288 return "InstallParams{"
7289 + Integer.toHexString(System.identityHashCode(this))
7290 + " " + mPackageURI + "}";
7291 }
7292
rich cannings706e8ba2012-08-20 13:20:14 -07007293 public ManifestDigest getManifestDigest() {
7294 if (verificationParams == null) {
7295 return null;
7296 }
7297 return verificationParams.getManifestDigest();
7298 }
7299
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007300 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
7301 String packageName = pkgLite.packageName;
7302 int installLocation = pkgLite.installLocation;
7303 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07007304 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007305 synchronized (mPackages) {
7306 PackageParser.Package pkg = mPackages.get(packageName);
7307 if (pkg != null) {
7308 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007309 // Check for downgrading.
7310 if ((flags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
7311 if (pkgLite.versionCode < pkg.mVersionCode) {
7312 Slog.w(TAG, "Can't install update of " + packageName
7313 + " update version " + pkgLite.versionCode
7314 + " is older than installed version "
7315 + pkg.mVersionCode);
7316 return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
7317 }
7318 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007319 // Check for updated system application.
7320 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7321 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007322 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007323 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
7324 }
7325 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
7326 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007327 if (onSd) {
7328 // Install flag overrides everything.
7329 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
7330 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07007331 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007332 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
7333 // Application explicitly specified internal.
7334 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
7335 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
7336 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07007337 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007338 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07007339 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07007340 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
7341 }
7342 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007343 }
7344 }
7345 } else {
7346 // Invalid install. Return error code
7347 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
7348 }
7349 }
7350 }
7351 // All the special cases have been taken care of.
7352 // Return result based on recommended install location.
7353 if (onSd) {
7354 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
7355 }
7356 return pkgLite.recommendedInstallLocation;
7357 }
7358
Adam Lesinski182f73f2013-12-05 16:48:06 -08007359 private long getMemoryLowThreshold() {
7360 final DeviceStorageMonitorInternal
7361 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
7362 if (dsm == null) {
7363 return 0L;
7364 }
7365 return dsm.getMemoryLowThreshold();
7366 }
7367
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007368 /*
7369 * Invoke remote method to get package information and install
7370 * location values. Override install location based on default
7371 * policy if needed and then create install arguments based
7372 * on the install location.
7373 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007374 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08007375 int ret = PackageManager.INSTALL_SUCCEEDED;
Kenny Root05ca4c92011-09-15 10:36:25 -07007376 final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
7377 final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
7378 PackageInfoLite pkgLite = null;
7379
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007380 if (onInt && onSd) {
7381 // Check if both bits are set.
7382 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
7383 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007384 } else {
Adam Lesinski182f73f2013-12-05 16:48:06 -08007385 final long lowThreshold = getMemoryLowThreshold();
7386 if (lowThreshold == 0L) {
Kenny Root62e1b4e2011-03-14 17:13:39 -07007387 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
Kenny Root62e1b4e2011-03-14 17:13:39 -07007388 }
7389
Kenny Root11128572010-10-11 10:51:32 -07007390 try {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007391 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
Kenny Root11128572010-10-11 10:51:32 -07007392 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root11128572010-10-11 10:51:32 -07007393
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007394 final File packageFile;
7395 if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007396 mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
7397 if (mTempPackage != null) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -08007398 ParcelFileDescriptor out;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007399 try {
7400 out = ParcelFileDescriptor.open(mTempPackage,
7401 ParcelFileDescriptor.MODE_READ_WRITE);
7402 } catch (FileNotFoundException e) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -08007403 out = null;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007404 Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
7405 }
7406
7407 // Make a temporary file for decryption.
7408 ret = mContainerService
7409 .copyResource(mPackageURI, encryptionParams, out);
Dianne Hackborn40e9f292012-11-27 19:12:23 -08007410 IoUtils.closeQuietly(out);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007411
7412 packageFile = mTempPackage;
7413
7414 FileUtils.setPermissions(packageFile.getAbsolutePath(),
Kenny Root0b2fa8c2012-09-14 10:26:16 -07007415 FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP
7416 | FileUtils.S_IROTH,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007417 -1, -1);
7418 } else {
7419 packageFile = null;
7420 }
7421 } else {
7422 packageFile = new File(mPackageURI.getPath());
7423 }
7424
7425 if (packageFile != null) {
7426 // Remote call to find out default install location
Kenny Rootcea37432012-10-18 14:57:33 -07007427 final String packageFilePath = packageFile.getAbsolutePath();
7428 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
7429 lowThreshold);
7430
7431 /*
7432 * If we have too little free space, try to free cache
7433 * before giving up.
7434 */
7435 if (pkgLite.recommendedInstallLocation
7436 == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
7437 final long size = mContainerService.calculateInstalledSize(
7438 packageFilePath, isForwardLocked());
7439 if (mInstaller.freeCache(size + lowThreshold) >= 0) {
7440 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
7441 flags, lowThreshold);
7442 }
Kenny Root3f96d0e2012-12-11 12:48:08 -08007443 /*
7444 * The cache free must have deleted the file we
7445 * downloaded to install.
7446 *
7447 * TODO: fix the "freeCache" call to not delete
7448 * the file we care about.
7449 */
7450 if (pkgLite.recommendedInstallLocation
7451 == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
7452 pkgLite.recommendedInstallLocation
7453 = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
7454 }
Kenny Rootcea37432012-10-18 14:57:33 -07007455 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007456 }
7457 } finally {
7458 mContext.revokeUriPermission(mPackageURI,
7459 Intent.FLAG_GRANT_READ_URI_PERMISSION);
7460 }
7461 }
7462
7463 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007464 int loc = pkgLite.recommendedInstallLocation;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007465 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007466 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007467 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08007468 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007469 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007470 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7471 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
7472 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Kenny Root1ebd74a2011-08-03 15:09:44 -07007473 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
7474 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007475 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
Kenny Root1ebd74a2011-08-03 15:09:44 -07007476 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007477 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007478 // Override with defaults if needed.
7479 loc = installLocationPolicy(pkgLite, flags);
Kenny Roota3e90792012-10-18 10:58:36 -07007480 if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
7481 ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
7482 } else if (!onSd && !onInt) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007483 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007484 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
7485 // Set the flag to install on external media.
7486 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007487 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007488 } else {
7489 // Make sure the flag for installing on external
7490 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07007491 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007492 flags &= ~PackageManager.INSTALL_EXTERNAL;
7493 }
7494 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007495 }
7496 }
Kenny Root5ab21572011-07-27 11:11:19 -07007497
7498 final InstallArgs args = createInstallArgs(this);
Kenny Root05ca4c92011-09-15 10:36:25 -07007499 mArgs = args;
7500
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007501 if (ret == PackageManager.INSTALL_SUCCEEDED) {
rich cannings36070b42012-10-09 11:50:15 -07007502 /*
7503 * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
7504 * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
7505 */
7506 int userIdentifier = getUser().getIdentifier();
7507 if (userIdentifier == UserHandle.USER_ALL
7508 && ((flags & PackageManager.INSTALL_FROM_ADB) != 0)) {
7509 userIdentifier = UserHandle.USER_OWNER;
7510 }
7511
Kenny Root5ab21572011-07-27 11:11:19 -07007512 /*
7513 * Determine if we have any installed package verifiers. If we
7514 * do, then we'll defer to them to verify the packages.
7515 */
Kenny Root05ca4c92011-09-15 10:36:25 -07007516 final int requiredUid = mRequiredVerifierPackage == null ? -1
rich cannings36070b42012-10-09 11:50:15 -07007517 : getPackageUid(mRequiredVerifierPackage, userIdentifier);
rich cannings4e5753f2012-09-19 16:03:56 -07007518 if (requiredUid != -1 && isVerificationEnabled(flags)) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007519 final Intent verification = new Intent(
7520 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
7521 verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
Kenny Root05ca4c92011-09-15 10:36:25 -07007522 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root5ab21572011-07-27 11:11:19 -07007523
Andy Stadler250ce282012-08-24 16:09:03 -07007524 final List<ResolveInfo> receivers = queryIntentReceivers(verification,
7525 PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
7526 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07007527
7528 if (DEBUG_VERIFY) {
Kenny Root5ab21572011-07-27 11:11:19 -07007529 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
Kenny Root05ca4c92011-09-15 10:36:25 -07007530 + verification.toString() + " with " + pkgLite.verifiers.length
7531 + " optional verifiers");
Kenny Root5ab21572011-07-27 11:11:19 -07007532 }
7533
7534 final int verificationId = mPendingVerificationToken++;
7535
7536 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
7537
7538 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
7539 installerPackageName);
7540
7541 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
7542
rich cannings13d428e2012-09-13 13:43:07 -07007543 verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
7544 pkgLite.packageName);
7545
7546 verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
7547 pkgLite.versionCode);
7548
rich cannings706e8ba2012-08-20 13:20:14 -07007549 if (verificationParams != null) {
7550 if (verificationParams.getVerificationURI() != null) {
7551 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
7552 verificationParams.getVerificationURI());
7553 }
7554 if (verificationParams.getOriginatingURI() != null) {
7555 verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
7556 verificationParams.getOriginatingURI());
7557 }
7558 if (verificationParams.getReferrer() != null) {
7559 verification.putExtra(Intent.EXTRA_REFERRER,
7560 verificationParams.getReferrer());
7561 }
Ben Gruver37d83a32012-09-27 13:02:06 -07007562 if (verificationParams.getOriginatingUid() >= 0) {
7563 verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
7564 verificationParams.getOriginatingUid());
7565 }
rich cannings13d428e2012-09-13 13:43:07 -07007566 if (verificationParams.getInstallerUid() >= 0) {
7567 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
7568 verificationParams.getInstallerUid());
7569 }
Kenny Root5ab21572011-07-27 11:11:19 -07007570 }
7571
Kenny Root05ca4c92011-09-15 10:36:25 -07007572 final PackageVerificationState verificationState = new PackageVerificationState(
7573 requiredUid, args);
7574
7575 mPendingVerification.append(verificationId, verificationState);
7576
7577 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
7578 receivers, verificationState);
Kenny Root5ab21572011-07-27 11:11:19 -07007579
7580 /*
Kenny Root05ca4c92011-09-15 10:36:25 -07007581 * If any sufficient verifiers were listed in the package
7582 * manifest, attempt to ask them.
Kenny Root5ab21572011-07-27 11:11:19 -07007583 */
Kenny Root05ca4c92011-09-15 10:36:25 -07007584 if (sufficientVerifiers != null) {
7585 final int N = sufficientVerifiers.size();
7586 if (N == 0) {
7587 Slog.i(TAG, "Additional verifiers required, but none installed.");
7588 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
7589 } else {
7590 for (int i = 0; i < N; i++) {
7591 final ComponentName verifierComponent = sufficientVerifiers.get(i);
7592
7593 final Intent sufficientIntent = new Intent(verification);
7594 sufficientIntent.setComponent(verifierComponent);
7595
rich canningsd55deb02012-10-02 14:53:08 -07007596 mContext.sendBroadcastAsUser(sufficientIntent, getUser());
Kenny Root05ca4c92011-09-15 10:36:25 -07007597 }
7598 }
7599 }
7600
7601 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
7602 mRequiredVerifierPackage, receivers);
7603 if (ret == PackageManager.INSTALL_SUCCEEDED
7604 && mRequiredVerifierPackage != null) {
7605 /*
7606 * Send the intent to the required verification agent,
7607 * but only start the verification timeout after the
7608 * target BroadcastReceivers have run.
7609 */
7610 verification.setComponent(requiredVerifierComponent);
rich canningsd55deb02012-10-02 14:53:08 -07007611 mContext.sendOrderedBroadcastAsUser(verification, getUser(),
Kenny Root05ca4c92011-09-15 10:36:25 -07007612 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
7613 new BroadcastReceiver() {
7614 @Override
7615 public void onReceive(Context context, Intent intent) {
7616 final Message msg = mHandler
7617 .obtainMessage(CHECK_PENDING_VERIFICATION);
7618 msg.arg1 = verificationId;
7619 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
7620 }
7621 }, null, 0, null, null);
7622
7623 /*
7624 * We don't want the copy to proceed until verification
7625 * succeeds, so null out this field.
7626 */
7627 mArgs = null;
7628 }
Kenny Root5ab21572011-07-27 11:11:19 -07007629 } else {
Kenny Root05ca4c92011-09-15 10:36:25 -07007630 /*
7631 * No package verification is enabled, so immediately start
7632 * the remote call to initiate copy using temporary file.
7633 */
Kenny Root5ab21572011-07-27 11:11:19 -07007634 ret = args.copyApk(mContainerService, true);
7635 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007636 }
Kenny Root5ab21572011-07-27 11:11:19 -07007637
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007638 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007639 }
7640
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007641 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007642 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07007643 // If mArgs is null, then MCS couldn't be reached. When it
7644 // reconnects, it will try again to install. At that point, this
7645 // will succeed.
7646 if (mArgs != null) {
7647 processPendingInstall(mArgs, mRet);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007648
Kenny Root0b2fa8c2012-09-14 10:26:16 -07007649 if (mTempPackage != null) {
7650 if (!mTempPackage.delete()) {
7651 Slog.w(TAG, "Couldn't delete temporary file: " +
7652 mTempPackage.getAbsolutePath());
7653 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007654 }
7655 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007656 }
7657
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007658 @Override
7659 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007660 mArgs = createInstallArgs(this);
7661 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007662 }
Kenny Root6dceb882012-04-12 14:23:49 -07007663
7664 public boolean isForwardLocked() {
7665 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
7666 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007667
7668 public Uri getPackageUri() {
7669 if (mTempPackage != null) {
7670 return Uri.fromFile(mTempPackage);
7671 } else {
7672 return mPackageURI;
7673 }
7674 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007675 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007676
7677 /*
7678 * Utility class used in movePackage api.
7679 * srcArgs and targetArgs are not set for invalid flags and make
7680 * sure to do null checks when invoking methods on them.
7681 * We probably want to return ErrorPrams for both failed installs
7682 * and moves.
7683 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007684 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007685 final IPackageMoveObserver observer;
7686 final int flags;
7687 final String packageName;
7688 final InstallArgs srcArgs;
7689 final InstallArgs targetArgs;
Kenny Root6dceb882012-04-12 14:23:49 -07007690 int uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007691 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07007692
7693 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
Amith Yamasani6ec10122012-08-23 13:49:25 -07007694 String packageName, String dataDir, int uid, UserHandle user) {
7695 super(user);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007696 this.srcArgs = srcArgs;
7697 this.observer = observer;
7698 this.flags = flags;
7699 this.packageName = packageName;
Kenny Root6dceb882012-04-12 14:23:49 -07007700 this.uid = uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007701 if (srcArgs != null) {
7702 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07007703 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007704 } else {
7705 targetArgs = null;
7706 }
7707 }
7708
Dianne Hackbornc895be72013-03-11 17:48:43 -07007709 @Override
7710 public String toString() {
7711 return "MoveParams{"
7712 + Integer.toHexString(System.identityHashCode(this))
7713 + " " + packageName + "}";
7714 }
7715
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007716 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007717 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7718 // Check for storage space on target medium
7719 if (!targetArgs.checkFreeStorage(mContainerService)) {
7720 Log.w(TAG, "Insufficient storage to install");
7721 return;
7722 }
Kenny Rootbf023582012-05-02 16:56:15 -07007723
7724 mRet = srcArgs.doPreCopy();
7725 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7726 return;
7727 }
7728
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007729 mRet = targetArgs.copyApk(mContainerService, false);
Kenny Rootbf023582012-05-02 16:56:15 -07007730 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7731 srcArgs.doPostCopy(uid);
7732 return;
7733 }
7734
7735 mRet = srcArgs.doPostCopy(uid);
7736 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7737 return;
7738 }
7739
7740 mRet = targetArgs.doPreInstall(mRet);
7741 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
7742 return;
7743 }
7744
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007745 if (DEBUG_SD_INSTALL) {
7746 StringBuilder builder = new StringBuilder();
7747 if (srcArgs != null) {
7748 builder.append("src: ");
7749 builder.append(srcArgs.getCodePath());
7750 }
7751 if (targetArgs != null) {
7752 builder.append(" target : ");
7753 builder.append(targetArgs.getCodePath());
7754 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007755 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007756 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007757 }
7758
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007759 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007760 void handleReturnCode() {
Kenny Root6dceb882012-04-12 14:23:49 -07007761 targetArgs.doPostInstall(mRet, uid);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007762 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
7763 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
7764 currentStatus = PackageManager.MOVE_SUCCEEDED;
7765 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
7766 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
7767 }
7768 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007769 }
7770
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007771 @Override
7772 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007773 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007774 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007775 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007776
Kenny Root6dceb882012-04-12 14:23:49 -07007777 /**
7778 * Used during creation of InstallArgs
7779 *
7780 * @param flags package installation flags
7781 * @return true if should be installed on external storage
7782 */
7783 private static boolean installOnSd(int flags) {
7784 if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
7785 return false;
7786 }
7787 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
7788 return true;
7789 }
7790 return false;
7791 }
7792
7793 /**
7794 * Used during creation of InstallArgs
7795 *
7796 * @param flags package installation flags
7797 * @return true if should be installed as forward locked
7798 */
7799 private static boolean installForwardLocked(int flags) {
7800 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
7801 }
7802
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007803 private InstallArgs createInstallArgs(InstallParams params) {
Kenny Root6dceb882012-04-12 14:23:49 -07007804 if (installOnSd(params.flags) || params.isForwardLocked()) {
7805 return new AsecInstallArgs(params);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007806 } else {
7807 return new FileInstallArgs(params);
7808 }
7809 }
7810
Kenny Root85387d72010-08-26 10:13:11 -07007811 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
7812 String nativeLibraryPath) {
Kenny Root84e35ea2012-06-06 16:05:05 -07007813 final boolean isInAsec;
7814 if (installOnSd(flags)) {
7815 /* Apps on SD card are always in ASEC containers. */
7816 isInAsec = true;
7817 } else if (installForwardLocked(flags)
7818 && !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
7819 /*
7820 * Forward-locked apps are only in ASEC containers if they're the
7821 * new style
7822 */
7823 isInAsec = true;
7824 } else {
7825 isInAsec = false;
7826 }
7827
7828 if (isInAsec) {
Kenny Root6dceb882012-04-12 14:23:49 -07007829 return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07007830 installOnSd(flags), installForwardLocked(flags));
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007831 } else {
Kenny Root85387d72010-08-26 10:13:11 -07007832 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007833 }
7834 }
7835
Kenny Root85387d72010-08-26 10:13:11 -07007836 // Used by package mover
7837 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Kenny Root6dceb882012-04-12 14:23:49 -07007838 if (installOnSd(flags) || installForwardLocked(flags)) {
Kenny Rootbf023582012-05-02 16:56:15 -07007839 String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
7840 + AsecInstallArgs.RES_FILE_NAME);
7841 return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
7842 installForwardLocked(flags));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007843 } else {
Kenny Root85387d72010-08-26 10:13:11 -07007844 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007845 }
7846 }
7847
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007848 static abstract class InstallArgs {
7849 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007850 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007851 final int flags;
7852 final Uri packageURI;
7853 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07007854 final ManifestDigest manifestDigest;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007855 final UserHandle user;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007856
Kenny Root5ab21572011-07-27 11:11:19 -07007857 InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007858 String installerPackageName, ManifestDigest manifestDigest,
7859 UserHandle user) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007860 this.packageURI = packageURI;
7861 this.flags = flags;
7862 this.observer = observer;
7863 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07007864 this.manifestDigest = manifestDigest;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007865 this.user = user;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007866 }
7867
7868 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007869 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007870 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007871 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Kenny Root6dceb882012-04-12 14:23:49 -07007872
7873 abstract int doPostInstall(int status, int uid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007874 abstract String getCodePath();
7875 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07007876 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007877 // Need installer lock especially for dex file removal.
7878 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007879 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007880 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Kenny Root6dceb882012-04-12 14:23:49 -07007881
Kenny Rootbf023582012-05-02 16:56:15 -07007882 /**
7883 * Called before the source arguments are copied. This is used mostly
7884 * for MoveParams when it needs to read the source file to put it in the
7885 * destination.
7886 */
7887 int doPreCopy() {
7888 return PackageManager.INSTALL_SUCCEEDED;
7889 }
7890
7891 /**
7892 * Called after the source arguments are copied. This is used mostly for
7893 * MoveParams when it needs to read the source file to put it in the
7894 * destination.
7895 *
7896 * @return
7897 */
7898 int doPostCopy(int uid) {
7899 return PackageManager.INSTALL_SUCCEEDED;
7900 }
7901
Kenny Root6dceb882012-04-12 14:23:49 -07007902 protected boolean isFwdLocked() {
7903 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
7904 }
rich canningsd55deb02012-10-02 14:53:08 -07007905
7906 UserHandle getUser() {
7907 return user;
7908 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007909 }
7910
7911 class FileInstallArgs extends InstallArgs {
7912 File installDir;
7913 String codeFileName;
7914 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07007915 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007916 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007917
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007918 FileInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007919 super(params.getPackageUri(), params.observer, params.flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007920 params.installerPackageName, params.getManifestDigest(),
7921 params.getUser());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007922 }
7923
Kenny Root85387d72010-08-26 10:13:11 -07007924 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007925 super(null, null, 0, null, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007926 File codeFile = new File(fullCodePath);
7927 installDir = codeFile.getParentFile();
7928 codeFileName = fullCodePath;
7929 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07007930 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007931 }
7932
Kenny Root85387d72010-08-26 10:13:11 -07007933 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007934 super(packageURI, null, 0, null, null, null);
Kenny Root85387d72010-08-26 10:13:11 -07007935 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007936 String apkName = getNextCodePath(null, pkgName, ".apk");
7937 codeFileName = new File(installDir, apkName + ".apk").getPath();
7938 resourceFileName = getResourcePathFromCodePath();
Kenny Rootddbe50d2012-09-06 13:18:37 -07007939 libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007940 }
7941
Kenny Root11128572010-10-11 10:51:32 -07007942 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07007943 final long lowThreshold;
7944
Adam Lesinski182f73f2013-12-05 16:48:06 -08007945 final DeviceStorageMonitorInternal
7946 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
Kenny Root62e1b4e2011-03-14 17:13:39 -07007947 if (dsm == null) {
7948 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
7949 lowThreshold = 0L;
7950 } else {
7951 if (dsm.isMemoryLow()) {
7952 Log.w(TAG, "Memory is reported as being too low; aborting package install");
7953 return false;
7954 }
7955
7956 lowThreshold = dsm.getMemoryLowThreshold();
7957 }
7958
Kenny Root11128572010-10-11 10:51:32 -07007959 try {
7960 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
7961 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07007962 return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07007963 } finally {
7964 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
7965 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007966 }
7967
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007968 String getCodePath() {
7969 return codeFileName;
7970 }
7971
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007972 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07007973 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007974 codeFileName = createTempPackageFile(installDir).getPath();
7975 resourceFileName = getResourcePathFromCodePath();
Kenny Rootddbe50d2012-09-06 13:18:37 -07007976 libraryPath = getLibraryPathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007977 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007978 }
7979
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007980 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007981 if (temp) {
7982 // Generate temp file name
7983 createCopyFile();
7984 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007985 // Get a ParcelFileDescriptor to write to the output file
7986 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007987 if (!created) {
7988 try {
7989 codeFile.createNewFile();
7990 // Set permissions
7991 if (!setPermissions()) {
7992 // Failed setting permissions.
7993 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7994 }
7995 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007996 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007997 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7998 }
7999 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008000 ParcelFileDescriptor out = null;
8001 try {
Kenny Root85387d72010-08-26 10:13:11 -07008002 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008003 } catch (FileNotFoundException e) {
Kenny Rootf5121a92011-08-10 16:23:32 -07008004 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008005 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8006 }
8007 // Copy the resource now
8008 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8009 try {
Kenny Root11128572010-10-11 10:51:32 -07008010 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
8011 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07008012 ret = imcs.copyResource(packageURI, null, out);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008013 } finally {
Kenny Root2782a472012-04-14 21:48:21 -07008014 IoUtils.closeQuietly(out);
Kenny Root11128572010-10-11 10:51:32 -07008015 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008016 }
Kenny Root85387d72010-08-26 10:13:11 -07008017
Kenny Root2782a472012-04-14 21:48:21 -07008018 if (isFwdLocked()) {
8019 final File destResourceFile = new File(getResourcePath());
8020
8021 // Copy the public files
8022 try {
8023 PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
8024 } catch (IOException e) {
8025 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
8026 + " forward-locked app.");
8027 destResourceFile.delete();
8028 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8029 }
8030 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07008031
8032 final File nativeLibraryFile = new File(getNativeLibraryPath());
8033 Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
8034 if (nativeLibraryFile.exists()) {
8035 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
8036 nativeLibraryFile.delete();
8037 }
8038 try {
8039 int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
8040 if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
8041 return copyRet;
8042 }
8043 } catch (IOException e) {
8044 Slog.e(TAG, "Copying native libraries failed", e);
8045 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
8046 }
8047
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008048 return ret;
8049 }
8050
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008051 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008052 if (status != PackageManager.INSTALL_SUCCEEDED) {
8053 cleanUp();
8054 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008055 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008056 }
8057
8058 boolean doRename(int status, final String pkgName, String oldCodePath) {
8059 if (status != PackageManager.INSTALL_SUCCEEDED) {
8060 cleanUp();
8061 return false;
8062 } else {
Kenny Root2782a472012-04-14 21:48:21 -07008063 final File oldCodeFile = new File(getCodePath());
8064 final File oldResourceFile = new File(getResourcePath());
Kenny Rootddbe50d2012-09-06 13:18:37 -07008065 final File oldLibraryFile = new File(getNativeLibraryPath());
Kenny Root2782a472012-04-14 21:48:21 -07008066
8067 // Rename APK file based on packageName
8068 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
8069 final File newCodeFile = new File(installDir, apkName + ".apk");
8070 if (!oldCodeFile.renameTo(newCodeFile)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008071 return false;
8072 }
Kenny Root2782a472012-04-14 21:48:21 -07008073 codeFileName = newCodeFile.getPath();
8074
8075 // Rename public resource file if it's forward-locked.
8076 final File newResFile = new File(getResourcePathFromCodePath());
8077 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
8078 return false;
8079 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07008080 resourceFileName = newResFile.getPath();
8081
8082 // Rename library path
8083 final File newLibraryFile = new File(getLibraryPathFromCodePath());
8084 if (newLibraryFile.exists()) {
8085 NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
8086 newLibraryFile.delete();
8087 }
8088 if (!oldLibraryFile.renameTo(newLibraryFile)) {
8089 Slog.e(TAG, "Cannot rename native library directory "
8090 + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
8091 return false;
8092 }
8093 libraryPath = newLibraryFile.getPath();
Kenny Root2782a472012-04-14 21:48:21 -07008094
8095 // Attempt to set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008096 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008097 return false;
8098 }
Kenny Root2782a472012-04-14 21:48:21 -07008099
rpcraig554cb0c2012-07-05 06:41:43 -04008100 if (!SELinux.restorecon(newCodeFile)) {
8101 return false;
8102 }
8103
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008104 return true;
8105 }
8106 }
8107
Kenny Root6dceb882012-04-12 14:23:49 -07008108 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008109 if (status != PackageManager.INSTALL_SUCCEEDED) {
8110 cleanUp();
8111 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008112 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008113 }
8114
8115 String getResourcePath() {
8116 return resourceFileName;
8117 }
8118
Kenny Root2782a472012-04-14 21:48:21 -07008119 private String getResourcePathFromCodePath() {
8120 final String codePath = getCodePath();
8121 if (isFwdLocked()) {
8122 final StringBuilder sb = new StringBuilder();
8123
8124 sb.append(mAppInstallDir.getPath());
8125 sb.append('/');
8126 sb.append(getApkName(codePath));
8127 sb.append(".zip");
8128
8129 /*
8130 * If our APK is a temporary file, mark the resource as a
8131 * temporary file as well so it can be cleaned up after
8132 * catastrophic failure.
8133 */
8134 if (codePath.endsWith(".tmp")) {
8135 sb.append(".tmp");
8136 }
8137
8138 return sb.toString();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008139 } else {
8140 return codePath;
8141 }
8142 }
8143
Kenny Rootddbe50d2012-09-06 13:18:37 -07008144 private String getLibraryPathFromCodePath() {
8145 return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
8146 }
8147
Kenny Root85387d72010-08-26 10:13:11 -07008148 @Override
8149 String getNativeLibraryPath() {
Kenny Rootddbe50d2012-09-06 13:18:37 -07008150 if (libraryPath == null) {
8151 libraryPath = getLibraryPathFromCodePath();
8152 }
Kenny Root85387d72010-08-26 10:13:11 -07008153 return libraryPath;
8154 }
8155
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008156 private boolean cleanUp() {
8157 boolean ret = true;
8158 String sourceDir = getCodePath();
8159 String publicSourceDir = getResourcePath();
8160 if (sourceDir != null) {
8161 File sourceFile = new File(sourceDir);
8162 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008163 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008164 ret = false;
8165 }
8166 // Delete application's code and resources
8167 sourceFile.delete();
8168 }
8169 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
8170 final File publicSourceFile = new File(publicSourceDir);
8171 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008172 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008173 }
8174 if (publicSourceFile.exists()) {
8175 publicSourceFile.delete();
8176 }
8177 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07008178
8179 if (libraryPath != null) {
8180 File nativeLibraryFile = new File(libraryPath);
8181 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
8182 if (!nativeLibraryFile.delete()) {
8183 Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
8184 }
8185 }
8186
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008187 return ret;
8188 }
8189
8190 void cleanUpResourcesLI() {
8191 String sourceDir = getCodePath();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008192 if (cleanUp()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008193 int retCode = mInstaller.rmdex(sourceDir);
8194 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008195 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008196 + " at location "
8197 + sourceDir + ", retcode=" + retCode);
8198 // we don't consider this to be a failure of the core package deletion
8199 }
8200 }
8201 }
8202
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008203 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008204 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07008205 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008206 final int filePermissions =
8207 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
8208 |FileUtils.S_IROTH;
8209 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
8210 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008211 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008212 getCodePath()
8213 + ". The return code was: " + retCode);
8214 // TODO Define new internal error
8215 return false;
8216 }
8217 return true;
8218 }
8219 return true;
8220 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008221
8222 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07008223 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008224 cleanUpResourcesLI();
8225 return true;
8226 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008227 }
8228
Kenny Root51a573c2012-05-17 13:30:28 -07008229 private boolean isAsecExternal(String cid) {
8230 final String asecPath = PackageHelper.getSdFilesystem(cid);
8231 return !asecPath.startsWith(mAsecInternalPath);
8232 }
8233
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008234 /**
8235 * Extract the MountService "container ID" from the full code path of an
8236 * .apk.
8237 */
8238 static String cidFromCodePath(String fullCodePath) {
8239 int eidx = fullCodePath.lastIndexOf("/");
8240 String subStr1 = fullCodePath.substring(0, eidx);
8241 int sidx = subStr1.lastIndexOf("/");
8242 return subStr1.substring(sidx+1, eidx);
8243 }
8244
Kenny Root6dceb882012-04-12 14:23:49 -07008245 class AsecInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008246 static final String RES_FILE_NAME = "pkg.apk";
Kenny Root6dceb882012-04-12 14:23:49 -07008247 static final String PUBLIC_RES_FILE_NAME = "res.zip";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008248
Kenny Root85387d72010-08-26 10:13:11 -07008249 String cid;
8250 String packagePath;
Kenny Root6dceb882012-04-12 14:23:49 -07008251 String resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07008252 String libraryPath;
8253
Kenny Root6dceb882012-04-12 14:23:49 -07008254 AsecInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07008255 super(params.getPackageUri(), params.observer, params.flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008256 params.installerPackageName, params.getManifestDigest(),
8257 params.getUser());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008258 }
8259
Kenny Root6dceb882012-04-12 14:23:49 -07008260 AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07008261 boolean isExternal, boolean isForwardLocked) {
8262 super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008263 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
8264 null, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008265 // Extract cid from fullCodePath
8266 int eidx = fullCodePath.lastIndexOf("/");
8267 String subStr1 = fullCodePath.substring(0, eidx);
8268 int sidx = subStr1.lastIndexOf("/");
8269 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07008270 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008271 }
8272
Kenny Rootc7a89992012-06-05 15:13:17 -07008273 AsecInstallArgs(String cid, boolean isForwardLocked) {
8274 super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008275 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
8276 null, null, null);
Dianne Hackbornaa77de12010-05-14 22:33:54 -07008277 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07008278 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008279 }
8280
Kenny Rootbf023582012-05-02 16:56:15 -07008281 AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
8282 super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008283 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
8284 null, null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008285 this.cid = cid;
8286 }
8287
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008288 void createCopyFile() {
8289 cid = getTempContainerId();
8290 }
8291
Kenny Root11128572010-10-11 10:51:32 -07008292 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
8293 try {
8294 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
8295 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07008296 return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07008297 } finally {
8298 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
8299 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08008300 }
8301
Kenny Root6dceb882012-04-12 14:23:49 -07008302 private final boolean isExternal() {
8303 return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
8304 }
8305
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008306 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008307 if (temp) {
8308 createCopyFile();
Kenny Rootf5121a92011-08-10 16:23:32 -07008309 } else {
8310 /*
8311 * Pre-emptively destroy the container since it's destroyed if
8312 * copying fails due to it existing anyway.
8313 */
8314 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008315 }
Kenny Root11128572010-10-11 10:51:32 -07008316
8317 final String newCachePath;
8318 try {
8319 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
8320 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07008321 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
8322 RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07008323 } finally {
8324 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
8325 }
8326
Kenny Root85387d72010-08-26 10:13:11 -07008327 if (newCachePath != null) {
8328 setCachePath(newCachePath);
8329 return PackageManager.INSTALL_SUCCEEDED;
8330 } else {
8331 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8332 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008333 }
8334
8335 @Override
8336 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07008337 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008338 }
8339
8340 @Override
8341 String getResourcePath() {
Kenny Root6dceb882012-04-12 14:23:49 -07008342 return resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07008343 }
8344
8345 @Override
8346 String getNativeLibraryPath() {
8347 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008348 }
8349
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008350 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008351 if (status != PackageManager.INSTALL_SUCCEEDED) {
8352 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008353 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008354 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008355 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008356 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07008357 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
8358 Process.SYSTEM_UID);
8359 if (newCachePath != null) {
8360 setCachePath(newCachePath);
8361 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008362 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8363 }
8364 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008365 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008366 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008367 }
8368
8369 boolean doRename(int status, final String pkgName,
8370 String oldCodePath) {
8371 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008372 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008373 if (PackageHelper.isContainerMounted(cid)) {
8374 // Unmount the container
8375 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008376 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008377 return false;
8378 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008379 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008380 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07008381 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
8382 " which might be stale. Will try to clean up.");
8383 // Clean up the stale container and proceed to recreate.
8384 if (!PackageHelper.destroySdDir(newCacheId)) {
8385 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
8386 return false;
8387 }
8388 // Successfully cleaned up stale container. Try to rename again.
8389 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
8390 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
8391 + " inspite of cleaning it up.");
8392 return false;
8393 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008394 }
8395 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008396 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008397 newCachePath = PackageHelper.mountSdDir(newCacheId,
8398 getEncryptKey(), Process.SYSTEM_UID);
8399 } else {
8400 newCachePath = PackageHelper.getSdDir(newCacheId);
8401 }
8402 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008403 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008404 return false;
8405 }
8406 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07008407 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008408 " at new path: " + newCachePath);
8409 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07008410 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008411 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008412 }
8413
Kenny Root85387d72010-08-26 10:13:11 -07008414 private void setCachePath(String newCachePath) {
8415 File cachePath = new File(newCachePath);
8416 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
8417 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
Kenny Root6dceb882012-04-12 14:23:49 -07008418
8419 if (isFwdLocked()) {
8420 resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
8421 } else {
8422 resourcePath = packagePath;
8423 }
Kenny Root85387d72010-08-26 10:13:11 -07008424 }
8425
Kenny Root6dceb882012-04-12 14:23:49 -07008426 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008427 if (status != PackageManager.INSTALL_SUCCEEDED) {
8428 cleanUp();
8429 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07008430 final int groupOwner;
8431 final String protectedFile;
8432 if (isFwdLocked()) {
Kenny Roote091f222012-09-11 15:01:26 -07008433 groupOwner = UserHandle.getSharedAppGid(uid);
Kenny Rootbf023582012-05-02 16:56:15 -07008434 protectedFile = RES_FILE_NAME;
8435 } else {
8436 groupOwner = -1;
8437 protectedFile = null;
8438 }
8439
Kenny Root6dceb882012-04-12 14:23:49 -07008440 if (uid < Process.FIRST_APPLICATION_UID
Kenny Rootbf023582012-05-02 16:56:15 -07008441 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Kenny Root6dceb882012-04-12 14:23:49 -07008442 Slog.e(TAG, "Failed to finalize " + cid);
8443 PackageHelper.destroySdDir(cid);
8444 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8445 }
8446
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008447 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008448 if (!mounted) {
Kenny Root6dceb882012-04-12 14:23:49 -07008449 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008450 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008451 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008452 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008453 }
8454
8455 private void cleanUp() {
Kenny Root6dceb882012-04-12 14:23:49 -07008456 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
8457
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008458 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008459 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008460 }
8461
8462 void cleanUpResourcesLI() {
8463 String sourceFile = getCodePath();
8464 // Remove dex file
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008465 int retCode = mInstaller.rmdex(sourceFile);
8466 if (retCode < 0) {
8467 Slog.w(TAG, "Couldn't remove dex file for package: "
8468 + " at location "
8469 + sourceFile.toString() + ", retcode=" + retCode);
8470 // we don't consider this to be a failure of the core package deletion
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008471 }
8472 cleanUp();
8473 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008474
8475 boolean matchContainer(String app) {
8476 if (cid.startsWith(app)) {
8477 return true;
8478 }
8479 return false;
8480 }
8481
8482 String getPackageName() {
Kenny Rootc7a89992012-06-05 15:13:17 -07008483 return getAsecPackageName(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008484 }
8485
8486 boolean doPostDeleteLI(boolean delete) {
8487 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008488 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008489 if (mounted) {
8490 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008491 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008492 }
8493 if (ret && delete) {
8494 cleanUpResourcesLI();
8495 }
8496 return ret;
8497 }
Kenny Rootbf023582012-05-02 16:56:15 -07008498
8499 @Override
8500 int doPreCopy() {
8501 if (isFwdLocked()) {
8502 if (!PackageHelper.fixSdPermissions(cid,
8503 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
8504 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8505 }
8506 }
8507
8508 return PackageManager.INSTALL_SUCCEEDED;
8509 }
8510
8511 @Override
8512 int doPostCopy(int uid) {
8513 if (isFwdLocked()) {
Kenny Rootbf023582012-05-02 16:56:15 -07008514 if (uid < Process.FIRST_APPLICATION_UID
Kenny Roote091f222012-09-11 15:01:26 -07008515 || !PackageHelper.fixSdPermissions(cid, UserHandle.getSharedAppGid(uid),
8516 RES_FILE_NAME)) {
Kenny Rootbf023582012-05-02 16:56:15 -07008517 Slog.e(TAG, "Failed to finalize " + cid);
8518 PackageHelper.destroySdDir(cid);
8519 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8520 }
8521 }
8522
8523 return PackageManager.INSTALL_SUCCEEDED;
8524 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008525 };
8526
Kenny Rootc7a89992012-06-05 15:13:17 -07008527 static String getAsecPackageName(String packageCid) {
8528 int idx = packageCid.lastIndexOf("-");
8529 if (idx == -1) {
8530 return packageCid;
8531 }
8532 return packageCid.substring(0, idx);
8533 }
8534
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008535 // Utility method used to create code paths based on package name and available index.
8536 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
8537 String idxStr = "";
8538 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008539 // Fall back to default value of idx=1 if prefix is not
8540 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008541 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00008542 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008543 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00008544 if (subStr.endsWith(suffix)) {
8545 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008546 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008547 // If oldCodePath already contains prefix find out the
8548 // ending index to either increment or decrement.
8549 int sidx = subStr.lastIndexOf(prefix);
8550 if (sidx != -1) {
8551 subStr = subStr.substring(sidx + prefix.length());
8552 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008553 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
8554 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008555 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008556 try {
8557 idx = Integer.parseInt(subStr);
8558 if (idx <= 1) {
8559 idx++;
8560 } else {
8561 idx--;
8562 }
8563 } catch(NumberFormatException e) {
8564 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008565 }
8566 }
8567 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008568 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008569 return prefix + idxStr;
8570 }
8571
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008572 // Utility method used to ignore ADD/REMOVE events
8573 // by directory observer.
8574 private static boolean ignoreCodePath(String fullPathStr) {
8575 String apkName = getApkName(fullPathStr);
8576 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
8577 if (idx != -1 && ((idx+1) < apkName.length())) {
8578 // Make sure the package ends with a numeral
8579 String version = apkName.substring(idx+1);
8580 try {
8581 Integer.parseInt(version);
8582 return true;
8583 } catch (NumberFormatException e) {}
8584 }
8585 return false;
8586 }
8587
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008588 // Utility method that returns the relative package path with respect
8589 // to the installation directory. Like say for /data/data/com.test-1.apk
8590 // string com.test-1 is returned.
8591 static String getApkName(String codePath) {
8592 if (codePath == null) {
8593 return null;
8594 }
8595 int sidx = codePath.lastIndexOf("/");
8596 int eidx = codePath.lastIndexOf(".");
8597 if (eidx == -1) {
8598 eidx = codePath.length();
8599 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008600 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008601 return null;
8602 }
8603 return codePath.substring(sidx+1, eidx);
8604 }
8605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 class PackageInstalledInfo {
8607 String name;
8608 int uid;
Dianne Hackborn786b4402012-08-27 15:14:02 -07008609 // The set of users that originally had this package installed.
8610 int[] origUsers;
8611 // The set of users that now have this package installed.
8612 int[] newUsers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 PackageParser.Package pkg;
8614 int returnCode;
8615 PackageRemovedInfo removedInfo;
8616 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008618 /*
8619 * Install a non-existing package.
8620 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008621 private void installNewPackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008622 int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02008623 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008625 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08008626
Dianne Hackbornc895be72013-03-11 17:48:43 -07008627 if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
Dave Burke383fa182012-10-23 23:12:19 -07008628 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07008630 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
8631 // A package with the same name is already installed, though
8632 // it has been renamed to an older name. The package we
8633 // are trying to install should be installed as an update to
8634 // the existing one, but that has not been requested, so bail.
8635 Slog.w(TAG, "Attempt to re-install " + pkgName
8636 + " without first uninstalling package running as "
8637 + mSettings.mRenamedPackages.get(pkgName));
8638 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
8639 return;
8640 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008641 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008643 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 + " without first uninstalling.");
8645 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
8646 return;
8647 }
8648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008650 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008651 System.currentTimeMillis(), user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008653 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
8655 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
8656 }
8657 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008658 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02008659 installerPackageName,
Christopher Tateacee6e92013-05-14 16:11:44 -07008660 null, null,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008661 res);
8662 // delete the partially installed application. the data directory will have to be
8663 // restored if it was already existing
8664 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
8665 // remove package from internal structures. Note that we want deletePackageX to
8666 // delete the package data and cache directories that it created in
8667 // scanPackageLocked, unless those directories existed before we even tried to
8668 // install.
Christopher Tateacee6e92013-05-14 16:11:44 -07008669 deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008670 dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008671 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 }
8673 }
8674 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008675
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008676 private void replacePackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008677 int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02008678 String installerPackageName, PackageInstalledInfo res) {
8679
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008680 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008681 String pkgName = pkg.packageName;
Christopher Tateacee6e92013-05-14 16:11:44 -07008682 int[] allUsers;
8683 boolean[] perUserInstalled;
8684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008685 // First find the old package info and check signatures
8686 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008687 oldPackage = mPackages.get(pkgName);
Dianne Hackbornc895be72013-03-11 17:48:43 -07008688 if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
Kenny Root447106f2011-03-23 11:00:15 -07008689 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07008690 != PackageManager.SIGNATURE_MATCH) {
Kenny Root8c11f1d2012-04-14 12:10:38 -07008691 Slog.w(TAG, "New package has a different signature: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
8693 return;
8694 }
Christopher Tateacee6e92013-05-14 16:11:44 -07008695
8696 // In case of rollback, remember per-user/profile install state
8697 PackageSetting ps = mSettings.mPackages.get(pkgName);
8698 allUsers = sUserManager.getUserIds();
8699 perUserInstalled = new boolean[allUsers.length];
8700 for (int i = 0; i < allUsers.length; i++) {
Dianne Hackborn2c44c742013-05-17 12:07:21 -07008701 perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
Christopher Tateacee6e92013-05-14 16:11:44 -07008702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 }
Kenny Root85387d72010-08-26 10:13:11 -07008704 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008705 if (sysPkg) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008706 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
Christopher Tateacee6e92013-05-14 16:11:44 -07008707 user, allUsers, perUserInstalled, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 } else {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008709 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
Christopher Tateacee6e92013-05-14 16:11:44 -07008710 user, allUsers, perUserInstalled, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 }
8712 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008714 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008715 PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
Christopher Tateacee6e92013-05-14 16:11:44 -07008716 int[] allUsers, boolean[] perUserInstalled,
Jacek Surazski65e13172009-04-28 15:26:38 +02008717 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 PackageParser.Package newPackage = null;
8719 String pkgName = deletedPackage.packageName;
8720 boolean deletedPkg = true;
8721 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008722
Dianne Hackbornc895be72013-03-11 17:48:43 -07008723 if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
8724 + deletedPackage);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008725 long origUpdateTime;
8726 if (pkg.mExtras != null) {
8727 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
8728 } else {
8729 origUpdateTime = 0;
8730 }
8731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 // First delete the existing package while retaining the data directory
Christopher Tateacee6e92013-05-14 16:11:44 -07008733 if (!deletePackageLI(pkgName, null, true, null, null, PackageManager.DELETE_KEEP_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008734 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008735 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
8737 deletedPkg = false;
8738 } else {
8739 // Successfully deleted the old package. Now proceed with re-installation
8740 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008741 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008742 System.currentTimeMillis(), user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008743 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008744 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
8746 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08008747 }
8748 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008749 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02008750 installerPackageName,
Christopher Tateacee6e92013-05-14 16:11:44 -07008751 allUsers, perUserInstalled,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008752 res);
8753 updatedSettings = true;
8754 }
8755 }
8756
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008757 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008758 // remove package from internal structures. Note that we want deletePackageX to
8759 // delete the package data and cache directories that it created in
8760 // scanPackageLocked, unless those directories existed before we even tried to
8761 // install.
8762 if(updatedSettings) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07008763 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764 deletePackageLI(
Christopher Tateacee6e92013-05-14 16:11:44 -07008765 pkgName, null, true, allUsers, perUserInstalled,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008766 PackageManager.DELETE_KEEP_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008767 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 }
8769 // Since we failed to install the new package we need to restore the old
8770 // package that we deleted.
8771 if(deletedPkg) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07008772 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07008773 File restoreFile = new File(deletedPackage.mPath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008774 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008775 boolean oldOnSd = isExternal(deletedPackage);
8776 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
8777 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
8778 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008779 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
8780 | SCAN_UPDATE_TIME;
8781 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
Dianne Hackborn786b4402012-08-27 15:14:02 -07008782 origUpdateTime, null) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008783 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
8784 return;
8785 }
8786 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07008787 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008788 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008789 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08008790 UPDATE_PERMISSIONS_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07008791 // can downgrade to reader
8792 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008793 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008794 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008795 }
8796 }
8797 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008800 PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
Christopher Tateacee6e92013-05-14 16:11:44 -07008801 int[] allUsers, boolean[] perUserInstalled,
Jacek Surazski65e13172009-04-28 15:26:38 +02008802 String installerPackageName, PackageInstalledInfo res) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07008803 if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
8804 + ", old=" + deletedPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 PackageParser.Package newPackage = null;
8806 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008807 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008808 PackageParser.PARSE_IS_SYSTEM;
Christopher Tate46eadae2013-06-26 14:20:18 -07008809 if ((deletedPackage.applicationInfo.flags&ApplicationInfo.FLAG_PRIVILEGED) != 0) {
8810 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
8811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 String packageName = deletedPackage.packageName;
8813 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
8814 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008815 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 return;
8817 }
8818 PackageParser.Package oldPkg;
8819 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07008820 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 synchronized (mPackages) {
8822 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008823 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008824 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
8825 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008826 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008827 return;
8828 }
8829 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008830
Dianne Hackborn21d9b562013-05-28 17:46:59 -07008831 killApplication(packageName, oldPkg.applicationInfo.uid, "replace sys pkg");
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833 res.removedInfo.uid = oldPkg.applicationInfo.uid;
8834 res.removedInfo.removedPackage = packageName;
8835 // Remove existing system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008836 removePackageLI(oldPkgSetting, true);
Kenny Root447106f2011-03-23 11:00:15 -07008837 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08008838 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008839 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008840 // We didn't need to disable the .apk as a current system package,
8841 // which means we are replacing another update that is already
8842 // installed. We need to make sure to delete the older one's .apk.
Kenny Root6dceb882012-04-12 14:23:49 -07008843 res.removedInfo.args = createInstallArgs(0,
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008844 deletedPackage.applicationInfo.sourceDir,
8845 deletedPackage.applicationInfo.publicSourceDir,
8846 deletedPackage.applicationInfo.nativeLibraryDir);
8847 } else {
8848 res.removedInfo.args = null;
8849 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08008850 }
8851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008852 // Successfully disabled the old package. Now proceed with re-installation
8853 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
8854 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008855 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008856 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008857 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008858 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
8859 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
8860 }
8861 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008862 if (newPackage.mExtras != null) {
8863 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
8864 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
8865 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
8866 }
Christopher Tateacee6e92013-05-14 16:11:44 -07008867 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 updatedSettings = true;
8869 }
8870
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008871 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 // Re installation failed. Restore old information
8873 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07008874 if (newPackage != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008875 removeInstalledPackageLI(newPackage, true);
Dianne Hackborn62da8462009-05-13 15:06:13 -07008876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008877 // Add back the old system package
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008878 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 // Restore the old system information in Settings
8880 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008881 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07008882 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02008883 mSettings.setInstallerPackageName(packageName,
8884 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 }
Kenny Root447106f2011-03-23 11:00:15 -07008886 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 }
8888 }
8889 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008890
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008891 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008892 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008893 int retCode;
8894 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
8895 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
8896 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07008897 if (mNoDexOpt) {
8898 /*
8899 * If we're in an engineering build, programs are lazily run
8900 * through dexopt. If the .dex file doesn't exist yet, it
8901 * will be created when the program is run next.
8902 */
8903 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
8904 } else {
8905 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
8906 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8907 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008908 }
8909 }
8910 return PackageManager.INSTALL_SUCCEEDED;
8911 }
8912
Christopher Tateacee6e92013-05-14 16:11:44 -07008913 private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
8914 int[] allUsers, boolean[] perUserInstalled,
8915 PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008916 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 synchronized (mPackages) {
8918 //write settings. the installStatus will be incomplete at this stage.
8919 //note that the new package setting would have already been
8920 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07008921 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07008922 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 }
8924
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008925 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008926 != PackageManager.INSTALL_SUCCEEDED) {
8927 // Discontinue if moving dex files failed.
8928 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008929 }
Kenny Root6dceb882012-04-12 14:23:49 -07008930
Dianne Hackbornc895be72013-03-11 17:48:43 -07008931 if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.mPath);
Kenny Root6dceb882012-04-12 14:23:49 -07008932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008934 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08008935 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
8936 ? UPDATE_PERMISSIONS_ALL : 0));
Christopher Tate32a019d2013-04-04 15:40:04 -07008937 // For system-bundled packages, we assume that installing an upgraded version
8938 // of the package implies that the user actually wants to run that new code,
8939 // so we enable the package.
8940 if (isSystemApp(newPackage)) {
8941 // NB: implicit assumption that system package upgrades apply to all users
8942 if (DEBUG_INSTALL) {
8943 Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName);
8944 }
8945 PackageSetting ps = mSettings.mPackages.get(pkgName);
8946 if (ps != null) {
8947 if (res.origUsers != null) {
8948 for (int userHandle : res.origUsers) {
8949 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT,
8950 userHandle, installerPackageName);
8951 }
8952 }
Christopher Tateacee6e92013-05-14 16:11:44 -07008953 // Also convey the prior install/uninstall state
8954 if (allUsers != null && perUserInstalled != null) {
8955 for (int i = 0; i < allUsers.length; i++) {
8956 if (DEBUG_INSTALL) {
8957 Slog.d(TAG, " user " + allUsers[i]
8958 + " => " + perUserInstalled[i]);
8959 }
8960 ps.setInstalled(perUserInstalled[i], allUsers[i]);
8961 }
8962 // these install state changes will be persisted in the
8963 // upcoming call to mSettings.writeLPr().
8964 }
Christopher Tate32a019d2013-04-04 15:40:04 -07008965 }
8966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 res.name = pkgName;
8968 res.uid = newPackage.applicationInfo.uid;
8969 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07008970 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02008971 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008972 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
8973 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07008974 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 }
8976 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008977
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008978 private void installPackageLI(InstallArgs args,
8979 boolean newInstall, PackageInstalledInfo res) {
8980 int pFlags = args.flags;
8981 String installerPackageName = args.installerPackageName;
8982 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008983 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08008984 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008985 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008986 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008987 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07008988 // Result object to be returned
8989 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
8990
Dianne Hackbornc895be72013-03-11 17:48:43 -07008991 if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008992 // Retrieve PackageSettings and parse package
Kenny Root6dceb882012-04-12 14:23:49 -07008993 int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
8994 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
8995 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008996 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
8997 pp.setSeparateProcesses(mSeparateProcesses);
8998 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
8999 null, mMetrics, parseFlags);
9000 if (pkg == null) {
9001 res.returnCode = pp.getParseError();
9002 return;
9003 }
9004 String pkgName = res.name = pkg.packageName;
9005 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
9006 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
9007 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
9008 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009009 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009010 }
9011 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
9012 res.returnCode = pp.getParseError();
9013 return;
9014 }
Kenny Root5ab21572011-07-27 11:11:19 -07009015
9016 /* If the installer passed in a manifest digest, compare it now. */
9017 if (args.manifestDigest != null) {
9018 if (DEBUG_INSTALL) {
9019 final String parsedManifest = pkg.manifestDigest == null ? "null"
9020 : pkg.manifestDigest.toString();
9021 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
9022 + parsedManifest);
9023 }
9024
9025 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
9026 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
9027 return;
9028 }
9029 } else if (DEBUG_INSTALL) {
9030 final String parsedManifest = pkg.manifestDigest == null
9031 ? "null" : pkg.manifestDigest.toString();
9032 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
9033 }
9034
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009035 // Get rid of all references to package scan path via parser.
9036 pp = null;
9037 String oldCodePath = null;
9038 boolean systemApp = false;
9039 synchronized (mPackages) {
9040 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009041 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
9042 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08009043 if (pkg.mOriginalPackages != null
9044 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009045 && mPackages.containsKey(oldName)) {
9046 // This package is derived from an original package,
9047 // and this device has been updating from that original
9048 // name. We must continue using the original name, so
9049 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08009050 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009051 pkgName = pkg.packageName;
9052 replace = true;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009053 if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
9054 + oldName + " pkgName=" + pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009055 } else if (mPackages.containsKey(pkgName)) {
9056 // This package, under its official name, already exists
9057 // on the device; we should replace it.
9058 replace = true;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009059 if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009060 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009061 }
9062 PackageSetting ps = mSettings.mPackages.get(pkgName);
9063 if (ps != null) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009064 if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009065 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
9066 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
9067 systemApp = (ps.pkg.applicationInfo.flags &
9068 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07009069 }
Dianne Hackborn786b4402012-08-27 15:14:02 -07009070 res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
Dianne Hackbornade3eca2009-05-11 18:54:45 -07009071 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009072 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009073
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009074 if (systemApp && onSd) {
9075 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009076 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009077 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
9078 return;
9079 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08009080
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009081 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
9082 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
9083 return;
9084 }
9085 // Set application objects path explicitly after the rename
9086 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07009087 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009088 if (replace) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009089 replacePackageLI(pkg, parseFlags, scanMode, args.user,
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009090 installerPackageName, res);
9091 } else {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009092 installNewPackageLI(pkg, parseFlags, scanMode, args.user,
Dianne Hackborn786b4402012-08-27 15:14:02 -07009093 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009095 synchronized (mPackages) {
Dianne Hackborn786b4402012-08-27 15:14:02 -07009096 final PackageSetting ps = mSettings.mPackages.get(pkgName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009097 if (ps != null) {
Dianne Hackborn786b4402012-08-27 15:14:02 -07009098 res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009099 }
9100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009102
Kenny Root85387d72010-08-26 10:13:11 -07009103 private static boolean isForwardLocked(PackageParser.Package pkg) {
9104 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009105 }
9106
Kenny Root88670d82012-05-09 15:47:35 -07009107
9108 private boolean isForwardLocked(PackageSetting ps) {
9109 return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
9110 }
9111
Kenny Root85387d72010-08-26 10:13:11 -07009112 private static boolean isExternal(PackageParser.Package pkg) {
9113 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
9114 }
9115
Kenny Root6dceb882012-04-12 14:23:49 -07009116 private static boolean isExternal(PackageSetting ps) {
9117 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
9118 }
9119
Kenny Root85387d72010-08-26 10:13:11 -07009120 private static boolean isSystemApp(PackageParser.Package pkg) {
9121 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
9122 }
9123
Christopher Tateccbf84f2013-05-08 15:25:41 -07009124 private static boolean isPrivilegedApp(PackageParser.Package pkg) {
9125 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
9126 }
9127
Kenny Root502e9a42011-01-10 13:48:15 -08009128 private static boolean isSystemApp(ApplicationInfo info) {
9129 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
9130 }
9131
Kenny Root208d3412012-05-07 19:42:35 -07009132 private static boolean isSystemApp(PackageSetting ps) {
9133 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
9134 }
9135
Nick Kralevich60792852013-04-03 14:12:24 -07009136 private static boolean isUpdatedSystemApp(PackageSetting ps) {
9137 return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
9138 }
9139
Kenny Root85387d72010-08-26 10:13:11 -07009140 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
9141 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009142 }
9143
Kenny Root88670d82012-05-09 15:47:35 -07009144 private int packageFlagsToInstallFlags(PackageSetting ps) {
9145 int installFlags = 0;
9146 if (isExternal(ps)) {
9147 installFlags |= PackageManager.INSTALL_EXTERNAL;
9148 }
9149 if (isForwardLocked(ps)) {
9150 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
9151 }
9152 return installFlags;
9153 }
9154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 private void deleteTempPackageFiles() {
Kenny Root0b2fa8c2012-09-14 10:26:16 -07009156 final FilenameFilter filter = new FilenameFilter() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 public boolean accept(File dir, String name) {
9158 return name.startsWith("vmdl") && name.endsWith(".tmp");
9159 }
9160 };
Kenny Root0b2fa8c2012-09-14 10:26:16 -07009161 deleteTempPackageFilesInDirectory(mAppInstallDir, filter);
9162 deleteTempPackageFilesInDirectory(mDrmAppPrivateInstallDir, filter);
9163 }
9164
9165 private static final void deleteTempPackageFilesInDirectory(File directory,
9166 FilenameFilter filter) {
9167 final String[] tmpFilesList = directory.list(filter);
9168 if (tmpFilesList == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009169 return;
9170 }
Kenny Root0b2fa8c2012-09-14 10:26:16 -07009171 for (int i = 0; i < tmpFilesList.length; i++) {
9172 final File tmpFile = new File(directory, tmpFilesList[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 tmpFile.delete();
9174 }
9175 }
9176
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009177 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 File tmpPackageFile;
9179 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009180 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009182 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 return null;
9184 }
9185 try {
9186 FileUtils.setPermissions(
9187 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
9188 -1, -1);
rpcraig554cb0c2012-07-05 06:41:43 -04009189 if (!SELinux.restorecon(tmpPackageFile)) {
9190 return null;
9191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009193 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 return null;
9195 }
9196 return tmpPackageFile;
9197 }
9198
Amith Yamasani67df64b2012-12-14 12:09:36 -08009199 @Override
9200 public void deletePackageAsUser(final String packageName,
9201 final IPackageDeleteObserver observer,
9202 final int userId, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 mContext.enforceCallingOrSelfPermission(
9204 android.Manifest.permission.DELETE_PACKAGES, null);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009205 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08009206 if (UserHandle.getUserId(uid) != userId) {
9207 mContext.enforceCallingPermission(
9208 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
9209 "deletePackage for user " + userId);
9210 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07009211 if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08009212 try {
9213 observer.packageDeleted(packageName, PackageManager.DELETE_FAILED_USER_RESTRICTED);
9214 } catch (RemoteException re) {
9215 }
9216 return;
9217 }
9218
Dianne Hackbornc895be72013-03-11 17:48:43 -07009219 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
Amith Yamasani67df64b2012-12-14 12:09:36 -08009220 // Queue up an async operation since the package deletion may take a little while.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 mHandler.post(new Runnable() {
9222 public void run() {
9223 mHandler.removeCallbacks(this);
Amith Yamasani67df64b2012-12-14 12:09:36 -08009224 final int returnCode = deletePackageX(packageName, userId, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 if (observer != null) {
9226 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08009227 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 } catch (RemoteException e) {
9229 Log.i(TAG, "Observer no longer exists.");
9230 } //end catch
9231 } //end if
9232 } //end run
9233 });
9234 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009235
Amith Yamasani655d0e22013-06-12 14:19:10 -07009236 private boolean isPackageDeviceAdmin(String packageName, int userId) {
9237 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
9238 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
9239 try {
9240 if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
9241 || dpm.isDeviceOwner(packageName))) {
9242 return true;
9243 }
9244 } catch (RemoteException e) {
9245 }
9246 return false;
9247 }
9248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 /**
9250 * This method is an internal method that could be get invoked either
9251 * to delete an installed package or to clean up a failed installation.
9252 * After deleting an installed package, a broadcast is sent to notify any
9253 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009254 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009255 * installation wouldn't have sent the initial broadcast either
9256 * The key steps in deleting a package are
9257 * deleting the package information in internal structures like mPackages,
9258 * deleting the packages base directories through installd
9259 * updating mSettings to reflect current status
9260 * persisting settings for later use
9261 * sending a broadcast if necessary
9262 */
Amith Yamasani67df64b2012-12-14 12:09:36 -08009263 private int deletePackageX(String packageName, int userId, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08009264 final PackageRemovedInfo info = new PackageRemovedInfo();
9265 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266
Amith Yamasani655d0e22013-06-12 14:19:10 -07009267 if (isPackageDeviceAdmin(packageName, userId)) {
9268 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
9269 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009270 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07009271
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009272 boolean removedForAllUsers = false;
9273 boolean systemUpdate = false;
Christopher Tateacee6e92013-05-14 16:11:44 -07009274
9275 // for the uninstall-updates case and restricted profiles, remember the per-
9276 // userhandle installed state
9277 int[] allUsers;
9278 boolean[] perUserInstalled;
9279 synchronized (mPackages) {
9280 PackageSetting ps = mSettings.mPackages.get(packageName);
9281 allUsers = sUserManager.getUserIds();
9282 perUserInstalled = new boolean[allUsers.length];
9283 for (int i = 0; i < allUsers.length; i++) {
Dianne Hackborn2c44c742013-05-17 12:07:21 -07009284 perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
Christopher Tateacee6e92013-05-14 16:11:44 -07009285 }
9286 }
9287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 synchronized (mInstallLock) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009289 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009290 res = deletePackageLI(packageName,
9291 (flags & PackageManager.DELETE_ALL_USERS) != 0
Amith Yamasani67df64b2012-12-14 12:09:36 -08009292 ? UserHandle.ALL : new UserHandle(userId),
Christopher Tateacee6e92013-05-14 16:11:44 -07009293 true, allUsers, perUserInstalled,
9294 flags | REMOVE_CHATTY, info, true);
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009295 systemUpdate = info.isRemovedPackageSystemUpdate;
9296 if (res && !systemUpdate && mPackages.get(packageName) == null) {
9297 removedForAllUsers = true;
9298 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009299 if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate
9300 + " removedForAllUsers=" + removedForAllUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009301 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009302
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009303 if (res) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009304 info.sendBroadcast(true, systemUpdate, removedForAllUsers);
Romain Guy96f43572009-03-24 20:27:49 -07009305
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009306 // If the removed package was a system update, the old system package
Romain Guy96f43572009-03-24 20:27:49 -07009307 // was re-enabled; we need to broadcast this information
9308 if (systemUpdate) {
9309 Bundle extras = new Bundle(1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009310 extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
9311 ? info.removedAppId : info.uid);
Romain Guy96f43572009-03-24 20:27:49 -07009312 extras.putBoolean(Intent.EXTRA_REPLACING, true);
9313
Dianne Hackborne7f97212011-02-24 14:40:20 -08009314 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009315 extras, null, null, null);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009316 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009317 extras, null, null, null);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009318 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009319 null, packageName, null, null);
Romain Guy96f43572009-03-24 20:27:49 -07009320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009321 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07009322 // Force a gc here.
9323 Runtime.getRuntime().gc();
9324 // Delete the resources here after sending the broadcast to let
9325 // other processes clean up before deleting resources.
9326 if (info.args != null) {
9327 synchronized (mInstallLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009328 info.args.doPostDeleteLI(true);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07009329 }
9330 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08009331
9332 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 }
9334
9335 static class PackageRemovedInfo {
9336 String removedPackage;
9337 int uid = -1;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009338 int removedAppId = -1;
9339 int[] removedUsers = null;
Romain Guy96f43572009-03-24 20:27:49 -07009340 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009341 // Clean up resources deleted packages.
9342 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07009343
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009344 void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 Bundle extras = new Bundle(1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009346 extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
9348 if (replacing) {
9349 extras.putBoolean(Intent.EXTRA_REPLACING, true);
9350 }
Dianne Hackbornc72fc672012-09-20 13:12:03 -07009351 extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009352 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08009353 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009354 extras, null, null, removedUsers);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07009355 if (fullRemove && !replacing) {
9356 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009357 extras, null, null, removedUsers);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07009358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009359 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009360 if (removedAppId >= 0) {
Amith Yamasani13593602012-03-22 16:16:17 -07009361 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009362 removedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 }
9364 }
9365 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009367 /*
9368 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
9369 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009370 * 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 -08009371 * delete a partially installed application.
9372 */
Christopher Tateacee6e92013-05-14 16:11:44 -07009373 private void removePackageDataLI(PackageSetting ps,
9374 int[] allUserHandles, boolean[] perUserInstalled,
9375 PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009376 String packageName = ps.name;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009377 if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009378 removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07009380 final PackageSetting deletedPs;
9381 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382 synchronized (mPackages) {
9383 deletedPs = mSettings.mPackages.get(packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009384 if (outInfo != null) {
9385 outInfo.removedPackage = packageName;
9386 outInfo.removedUsers = deletedPs != null
Dianne Hackborn786b4402012-08-27 15:14:02 -07009387 ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
9388 : null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009390 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009391 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
Dianne Hackborn4428e172012-08-24 17:43:05 -07009392 removeDataDirsLI(packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009393 schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 }
Kenny Root447106f2011-03-23 11:00:15 -07009395 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08009397 if (deletedPs != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009398 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009399 if (outInfo != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009400 outInfo.removedAppId = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009401 }
9402 if (deletedPs != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08009403 updatePermissionsLPw(deletedPs.name, null, 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009404 if (deletedPs.sharedUser != null) {
9405 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07009406 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009407 }
9408 }
Amith Yamasania3f133a2012-08-09 17:11:28 -07009409 clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08009410 }
Christopher Tateacee6e92013-05-14 16:11:44 -07009411 // make sure to preserve per-user disabled state if this removal was just
9412 // a downgrade of a system app to the factory package
9413 if (allUserHandles != null && perUserInstalled != null) {
9414 if (DEBUG_REMOVE) {
9415 Slog.d(TAG, "Propagating install state across downgrade");
9416 }
9417 for (int i = 0; i < allUserHandles.length; i++) {
9418 if (DEBUG_REMOVE) {
9419 Slog.d(TAG, " user " + allUserHandles[i]
9420 + " => " + perUserInstalled[i]);
9421 }
9422 ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
9423 }
9424 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08009425 }
Kenny Root447106f2011-03-23 11:00:15 -07009426 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009427 if (writeSettings) {
9428 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07009429 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 }
Kenny Root3b9933d2013-04-08 16:05:00 -07009432 if (outInfo != null) {
9433 // A user ID was deleted here. Go through all users and remove it
9434 // from KeyStore.
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009435 removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId);
Kenny Rootd72317a2013-04-01 15:59:59 -07009436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009437 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009438
Christopher Tate628946a2013-10-18 18:11:05 -07009439 static boolean locationIsPrivileged(File path) {
Christopher Tate0fe85a92013-10-04 19:40:09 -07009440 try {
9441 final String privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app")
9442 .getCanonicalPath();
9443 return path.getCanonicalPath().startsWith(privilegedAppDir);
9444 } catch (IOException e) {
9445 Slog.e(TAG, "Unable to access code path " + path);
9446 }
9447 return false;
9448 }
9449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009450 /*
9451 * Tries to delete system package.
9452 */
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009453 private boolean deleteSystemPackageLI(PackageSetting newPs,
Christopher Tateacee6e92013-05-14 16:11:44 -07009454 int[] allUserHandles, boolean[] perUserInstalled,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009455 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
Christopher Tateacee6e92013-05-14 16:11:44 -07009456 final boolean applyUserRestrictions
9457 = (allUserHandles != null) && (perUserInstalled != null);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009458 PackageSetting disabledPs = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459 // Confirm if the system package has been updated
9460 // An updated system app can be deleted. This will also have to restore
9461 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07009462 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009463 synchronized (mPackages) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009464 disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009466 if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + newPs
9467 + " disabledPs=" + disabledPs);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009468 if (disabledPs == null) {
9469 Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009470 return false;
Dianne Hackbornc895be72013-03-11 17:48:43 -07009471 } else if (DEBUG_REMOVE) {
9472 Slog.d(TAG, "Deleting system pkg from data partition");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 }
Christopher Tateacee6e92013-05-14 16:11:44 -07009474 if (DEBUG_REMOVE) {
9475 if (applyUserRestrictions) {
9476 Slog.d(TAG, "Remembering install states:");
9477 for (int i = 0; i < allUserHandles.length; i++) {
9478 Slog.d(TAG, " u=" + allUserHandles[i] + " inst=" + perUserInstalled[i]);
9479 }
9480 }
9481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07009483 outInfo.isRemovedPackageSystemUpdate = true;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009484 if (disabledPs.versionCode < newPs.versionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08009485 // Delete data for downgrades
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009486 flags &= ~PackageManager.DELETE_KEEP_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009487 } else {
9488 // Preserve data by setting flag
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009489 flags |= PackageManager.DELETE_KEEP_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009490 }
Christopher Tateacee6e92013-05-14 16:11:44 -07009491 boolean ret = deleteInstalledPackageLI(newPs, true, flags,
9492 allUserHandles, perUserInstalled, outInfo, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 if (!ret) {
9494 return false;
9495 }
Kenny Root447106f2011-03-23 11:00:15 -07009496 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497 synchronized (mPackages) {
9498 // Reinstate the old system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009499 mSettings.enableSystemPackageLPw(newPs.name);
Kenny Root8f7cc022010-09-12 09:04:56 -07009500 // Remove any native libraries from the upgraded package.
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009501 NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 }
9503 // Install the system package
Dianne Hackbornc895be72013-03-11 17:48:43 -07009504 if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
Christopher Tate0fe85a92013-10-04 19:40:09 -07009505 int parseFlags = PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM;
9506 if (locationIsPrivileged(disabledPs.codePath)) {
9507 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
9508 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009509 PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
Christopher Tate0fe85a92013-10-04 19:40:09 -07009510 parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 if (newPkg == null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009513 Slog.w(TAG, "Failed to restore system package:" + newPs.name
9514 + " with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515 return false;
9516 }
Kenny Root447106f2011-03-23 11:00:15 -07009517 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 synchronized (mPackages) {
Dianne Hackborne639da72012-02-21 15:11:13 -08009519 updatePermissionsLPw(newPkg.packageName, newPkg,
9520 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
Christopher Tateacee6e92013-05-14 16:11:44 -07009521 if (applyUserRestrictions) {
9522 if (DEBUG_REMOVE) {
9523 Slog.d(TAG, "Propagating install state across reinstall");
9524 }
9525 PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
9526 for (int i = 0; i < allUserHandles.length; i++) {
9527 if (DEBUG_REMOVE) {
9528 Slog.d(TAG, " user " + allUserHandles[i]
9529 + " => " + perUserInstalled[i]);
9530 }
9531 ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
9532 }
9533 // Regardless of writeSettings we need to ensure that this restriction
9534 // state propagation is persisted
9535 mSettings.writeAllUsersPackageRestrictionsLPr();
9536 }
Kenny Root447106f2011-03-23 11:00:15 -07009537 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009538 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07009539 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009541 }
9542 return true;
9543 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07009544
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009545 private boolean deleteInstalledPackageLI(PackageSetting ps,
Christopher Tateacee6e92013-05-14 16:11:44 -07009546 boolean deleteCodeAndResources, int flags,
9547 int[] allUserHandles, boolean[] perUserInstalled,
9548 PackageRemovedInfo outInfo, boolean writeSettings) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07009549 if (outInfo != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009550 outInfo.uid = ps.appId;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07009551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552
9553 // Delete package data from internal structures and also remove data if flag is set
Christopher Tateacee6e92013-05-14 16:11:44 -07009554 removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555
9556 // Delete application code and resources
Kenny Root92bc9b32012-10-23 17:42:40 -07009557 if (deleteCodeAndResources && (outInfo != null)) {
Kenny Root5455f682012-09-09 14:52:10 -07009558 outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009559 ps.resourcePathString, ps.nativeLibraryPathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009560 }
9561 return true;
9562 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009564 /*
9565 * This method handles package deletion in general
9566 */
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009567 private boolean deletePackageLI(String packageName, UserHandle user,
Christopher Tateacee6e92013-05-14 16:11:44 -07009568 boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,
9569 int flags, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009570 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009571 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009572 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 return false;
9574 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009575 if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009576 PackageSetting ps;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 boolean dataOnly = false;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009578 int removeUser = -1;
9579 int appId = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 synchronized (mPackages) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009581 ps = mSettings.mPackages.get(packageName);
9582 if (ps == null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009583 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
9584 return false;
9585 }
Dianne Hackbornc895be72013-03-11 17:48:43 -07009586 if ((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009587 && user.getIdentifier() != UserHandle.USER_ALL) {
9588 // The caller is asking that the package only be deleted for a single
9589 // user. To do this, we just mark its uninstalled state and delete
Dianne Hackbornc895be72013-03-11 17:48:43 -07009590 // its data. If this is a system app, we only allow this to happen if
9591 // they have set the special DELETE_SYSTEM_APP which requests different
9592 // semantics than normal for uninstalling system apps.
9593 if (DEBUG_REMOVE) Slog.d(TAG, "Only deleting for single user");
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009594 ps.setUserState(user.getIdentifier(),
9595 COMPONENT_ENABLED_STATE_DEFAULT,
9596 false, //installed
9597 true, //stopped
9598 true, //notLaunched
Amith Yamasani655d0e22013-06-12 14:19:10 -07009599 false, //blocked
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -07009600 null, null, null);
Amith Yamasani67df64b2012-12-14 12:09:36 -08009601 if (!isSystemApp(ps)) {
9602 if (ps.isAnyInstalled(sUserManager.getUserIds())) {
9603 // Other user still have this package installed, so all
9604 // we need to do is clear this user's data and save that
9605 // it is uninstalled.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009606 if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
Amith Yamasani67df64b2012-12-14 12:09:36 -08009607 removeUser = user.getIdentifier();
9608 appId = ps.appId;
9609 mSettings.writePackageRestrictionsLPr(removeUser);
9610 } else {
9611 // We need to set it back to 'installed' so the uninstall
9612 // broadcasts will be sent correctly.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009613 if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
Amith Yamasani67df64b2012-12-14 12:09:36 -08009614 ps.setInstalled(true, user.getIdentifier());
9615 }
9616 } else {
9617 // This is a system app, so we assume that the
9618 // other users still have this package installed, so all
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009619 // we need to do is clear this user's data and save that
9620 // it is uninstalled.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009621 if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009622 removeUser = user.getIdentifier();
9623 appId = ps.appId;
9624 mSettings.writePackageRestrictionsLPr(removeUser);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009625 }
9626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009628
9629 if (removeUser >= 0) {
9630 // From above, we determined that we are deleting this only
9631 // for a single user. Continue the work here.
Dianne Hackbornc895be72013-03-11 17:48:43 -07009632 if (DEBUG_REMOVE) Slog.d(TAG, "Updating install state for user: " + removeUser);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009633 if (outInfo != null) {
9634 outInfo.removedPackage = packageName;
9635 outInfo.removedAppId = appId;
9636 outInfo.removedUsers = new int[] {removeUser};
9637 }
9638 mInstaller.clearUserData(packageName, removeUser);
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009639 removeKeystoreDataIfNeeded(removeUser, appId);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009640 schedulePackageCleaning(packageName, removeUser, false);
9641 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 if (dataOnly) {
9645 // Delete application data first
Dianne Hackbornc895be72013-03-11 17:48:43 -07009646 if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
Christopher Tateacee6e92013-05-14 16:11:44 -07009647 removePackageDataLI(ps, null, null, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009648 return true;
9649 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08009650
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009651 boolean ret = false;
Geremy Condraf1bcca82013-01-07 22:35:24 -08009652 mSettings.mKeySetManager.removeAppKeySetData(packageName);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07009653 if (isSystemApp(ps)) {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009654 if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655 // When an updated system application is deleted we delete the existing resources as well and
9656 // fall back to existing code in system partition
Christopher Tateacee6e92013-05-14 16:11:44 -07009657 ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,
9658 flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009659 } else {
Dianne Hackbornc895be72013-03-11 17:48:43 -07009660 if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009661 // Kill application pre-emptively especially for apps on sd.
Dianne Hackborn21d9b562013-05-28 17:46:59 -07009662 killApplication(packageName, ps.appId, "uninstall pkg");
Christopher Tateacee6e92013-05-14 16:11:44 -07009663 ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,
9664 allUserHandles, perUserInstalled,
9665 outInfo, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009666 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08009667
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009668 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009669 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009670
Dianne Hackborn183ce022012-06-29 15:00:21 -07009671 private final class ClearStorageConnection implements ServiceConnection {
9672 IMediaContainerService mContainerService;
9673
9674 @Override
9675 public void onServiceConnected(ComponentName name, IBinder service) {
9676 synchronized (this) {
9677 mContainerService = IMediaContainerService.Stub.asInterface(service);
9678 notifyAll();
9679 }
9680 }
9681
9682 @Override
9683 public void onServiceDisconnected(ComponentName name) {
9684 }
9685 }
9686
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009687 private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
Dianne Hackborn183ce022012-06-29 15:00:21 -07009688 final boolean mounted;
9689 if (Environment.isExternalStorageEmulated()) {
9690 mounted = true;
9691 } else {
9692 final String status = Environment.getExternalStorageState();
9693
9694 mounted = status.equals(Environment.MEDIA_MOUNTED)
9695 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
9696 }
9697
9698 if (!mounted) {
9699 return;
9700 }
9701
9702 final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009703 int[] users;
9704 if (userId == UserHandle.USER_ALL) {
9705 users = sUserManager.getUserIds();
9706 } else {
9707 users = new int[] { userId };
9708 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07009709 final ClearStorageConnection conn = new ClearStorageConnection();
Amith Yamasani27b89e62013-01-16 12:30:11 -08009710 if (mContext.bindServiceAsUser(
9711 containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
Jeff Sharkey752cd922012-09-23 16:25:12 -07009712 try {
9713 for (int curUser : users) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009714 long timeout = SystemClock.uptimeMillis() + 5000;
9715 synchronized (conn) {
9716 long now = SystemClock.uptimeMillis();
9717 while (conn.mContainerService == null && now < timeout) {
9718 try {
9719 conn.wait(timeout - now);
9720 } catch (InterruptedException e) {
9721 }
Dianne Hackborn183ce022012-06-29 15:00:21 -07009722 }
9723 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009724 if (conn.mContainerService == null) {
9725 return;
9726 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07009727
9728 final UserEnvironment userEnv = new UserEnvironment(curUser);
Jeff Sharkey1abdb712013-08-11 16:28:14 -07009729 clearDirectory(conn.mContainerService,
9730 userEnv.buildExternalStorageAppCacheDirs(packageName));
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009731 if (allData) {
Jeff Sharkey1abdb712013-08-11 16:28:14 -07009732 clearDirectory(conn.mContainerService,
9733 userEnv.buildExternalStorageAppDataDirs(packageName));
9734 clearDirectory(conn.mContainerService,
9735 userEnv.buildExternalStorageAppMediaDirs(packageName));
Dianne Hackborn183ce022012-06-29 15:00:21 -07009736 }
9737 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07009738 } finally {
9739 mContext.unbindService(conn);
Dianne Hackborn183ce022012-06-29 15:00:21 -07009740 }
9741 }
9742 }
9743
Amith Yamasani483f3b02012-03-13 16:08:00 -07009744 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 public void clearApplicationUserData(final String packageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07009746 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747 mContext.enforceCallingOrSelfPermission(
9748 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
Amith Yamasanif203aee2012-08-29 18:41:53 -07009749 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "clear application data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 // Queue up an async operation since the package deletion may take a little while.
9751 mHandler.post(new Runnable() {
9752 public void run() {
9753 mHandler.removeCallbacks(this);
9754 final boolean succeeded;
9755 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07009756 succeeded = clearApplicationUserDataLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009758 clearExternalStorageDataSync(packageName, userId, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 if (succeeded) {
9760 // invoke DeviceStorageMonitor's update method to clear any notifications
Adam Lesinski182f73f2013-12-05 16:48:06 -08009761 DeviceStorageMonitorInternal
9762 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009763 if (dsm != null) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08009764 dsm.checkMemory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 }
9766 }
9767 if(observer != null) {
9768 try {
9769 observer.onRemoveCompleted(packageName, succeeded);
9770 } catch (RemoteException e) {
9771 Log.i(TAG, "Observer no longer exists.");
9772 }
9773 } //end if observer
9774 } //end run
9775 });
9776 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009777
Amith Yamasani483f3b02012-03-13 16:08:00 -07009778 private boolean clearApplicationUserDataLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009779 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009780 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 return false;
9782 }
9783 PackageParser.Package p;
9784 boolean dataOnly = false;
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009785 final int appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 synchronized (mPackages) {
9787 p = mPackages.get(packageName);
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009788 if (p == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 dataOnly = true;
9790 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009791 if ((ps == null) || (ps.pkg == null)) {
9792 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 return false;
9794 }
9795 p = ps.pkg;
9796 }
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009797 if (!dataOnly) {
9798 // need to check this only for fully installed applications
9799 if (p == null) {
9800 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
9801 return false;
9802 }
9803 final ApplicationInfo applicationInfo = p.applicationInfo;
9804 if (applicationInfo == null) {
9805 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
9806 return false;
9807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 }
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009809 if (p != null && p.applicationInfo != null) {
9810 appId = p.applicationInfo.uid;
9811 } else {
9812 appId = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07009815 int retCode = mInstaller.clearUserData(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009816 if (retCode < 0) {
9817 Slog.w(TAG, "Couldn't remove cache files for package: "
9818 + packageName);
9819 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 }
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009821 removeKeystoreDataIfNeeded(userId, appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 return true;
9823 }
9824
Kenny Root6fd1c85d2013-04-12 10:06:51 -07009825 /**
9826 * Remove entries from the keystore daemon. Will only remove it if the
9827 * {@code appId} is valid.
9828 */
9829 private static void removeKeystoreDataIfNeeded(int userId, int appId) {
9830 if (appId < 0) {
9831 return;
9832 }
9833
9834 final KeyStore keyStore = KeyStore.getInstance();
9835 if (keyStore != null) {
9836 if (userId == UserHandle.USER_ALL) {
9837 for (final int individual : sUserManager.getUserIds()) {
9838 keyStore.clearUid(UserHandle.getUid(individual, appId));
9839 }
9840 } else {
9841 keyStore.clearUid(UserHandle.getUid(userId, appId));
9842 }
9843 } else {
9844 Slog.w(TAG, "Could not contact keystore to clear entries for app id " + appId);
9845 }
9846 }
9847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009848 public void deleteApplicationCacheFiles(final String packageName,
9849 final IPackageDataObserver observer) {
9850 mContext.enforceCallingOrSelfPermission(
9851 android.Manifest.permission.DELETE_CACHE_FILES, null);
9852 // Queue up an async operation since the package deletion may take a little while.
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07009853 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 mHandler.post(new Runnable() {
9855 public void run() {
9856 mHandler.removeCallbacks(this);
9857 final boolean succeded;
9858 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07009859 succeded = deleteApplicationCacheFilesLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009861 clearExternalStorageDataSync(packageName, userId, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009862 if(observer != null) {
9863 try {
9864 observer.onRemoveCompleted(packageName, succeded);
9865 } catch (RemoteException e) {
9866 Log.i(TAG, "Observer no longer exists.");
9867 }
9868 } //end if observer
9869 } //end run
9870 });
9871 }
9872
Amith Yamasani483f3b02012-03-13 16:08:00 -07009873 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009875 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 return false;
9877 }
9878 PackageParser.Package p;
9879 synchronized (mPackages) {
9880 p = mPackages.get(packageName);
9881 }
9882 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009883 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 return false;
9885 }
9886 final ApplicationInfo applicationInfo = p.applicationInfo;
9887 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009888 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 return false;
9890 }
Amith Yamasani54289b82012-10-01 10:39:14 -07009891 int retCode = mInstaller.deleteCacheFiles(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009892 if (retCode < 0) {
9893 Slog.w(TAG, "Couldn't remove cache files for package: "
Amith Yamasani54289b82012-10-01 10:39:14 -07009894 + packageName + " u" + userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009895 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 }
9897 return true;
9898 }
9899
Dianne Hackborn0c380492012-08-20 17:23:30 -07009900 public void getPackageSizeInfo(final String packageName, int userHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 final IPackageStatsObserver observer) {
9902 mContext.enforceCallingOrSelfPermission(
9903 android.Manifest.permission.GET_PACKAGE_SIZE, null);
Kenny Root366949c2011-01-14 17:18:14 -08009904
Dianne Hackborn0c380492012-08-20 17:23:30 -07009905 PackageStats stats = new PackageStats(packageName, userHandle);
Kenny Root366949c2011-01-14 17:18:14 -08009906
Kenny Roota69b7eb2012-05-14 14:47:06 -07009907 /*
9908 * Queue up an async operation since the package measurement may take a
9909 * little while.
9910 */
9911 Message msg = mHandler.obtainMessage(INIT_COPY);
9912 msg.obj = new MeasureParams(stats, observer);
9913 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 }
9915
Dianne Hackborn0c380492012-08-20 17:23:30 -07009916 private boolean getPackageSizeInfoLI(String packageName, int userHandle,
9917 PackageStats pStats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009919 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 return false;
9921 }
9922 PackageParser.Package p;
9923 boolean dataOnly = false;
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009924 String libDirPath = null;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07009925 String asecPath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 synchronized (mPackages) {
9927 p = mPackages.get(packageName);
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009928 PackageSetting ps = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 if(p == null) {
9930 dataOnly = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009932 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 return false;
9934 }
9935 p = ps.pkg;
9936 }
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009937 if (ps != null) {
9938 libDirPath = ps.nativeLibraryPathString;
9939 }
Kenny Root2afded12012-06-04 16:39:47 -07009940 if (p != null && (isExternal(p) || isForwardLocked(p))) {
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07009941 String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
9942 if (secureContainerId != null) {
9943 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
9944 }
9945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 }
9947 String publicSrcDir = null;
9948 if(!dataOnly) {
9949 final ApplicationInfo applicationInfo = p.applicationInfo;
9950 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009951 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 return false;
9953 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07009954 if (isForwardLocked(p)) {
9955 publicSrcDir = applicationInfo.publicSourceDir;
9956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 }
Dianne Hackbornecc8d6f2013-05-01 18:54:11 -07009958 int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, libDirPath,
9959 publicSrcDir, asecPath, pStats);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07009960 if (res < 0) {
9961 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 }
Kenny Root2afded12012-06-04 16:39:47 -07009963
9964 // Fix-up for forward-locked applications in ASEC containers.
9965 if (!isExternal(p)) {
9966 pStats.codeSize += pStats.externalCodeSize;
9967 pStats.externalCodeSize = 0L;
9968 }
9969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 return true;
9971 }
9972
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07009975 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 }
9977
9978 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07009979 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 }
9981
9982 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08009983 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 }
9985
Kenny Root447106f2011-03-23 11:00:15 -07009986 private int getUidTargetSdkVersionLockedLPr(int uid) {
9987 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009988 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07009989 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009990 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07009991 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009992 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07009993 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009994 if (ps.pkg != null) {
9995 int v = ps.pkg.applicationInfo.targetSdkVersion;
9996 if (v < vers) vers = v;
9997 }
9998 }
9999 return vers;
10000 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -070010001 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010002 if (ps.pkg != null) {
10003 return ps.pkg.applicationInfo.targetSdkVersion;
10004 }
10005 }
10006 return Build.VERSION_CODES.CUR_DEVELOPMENT;
10007 }
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 public void addPreferredActivity(IntentFilter filter, int match,
Amith Yamasania3f133a2012-08-09 17:11:28 -070010010 ComponentName[] set, ComponentName activity, int userId) {
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010011 addPreferredActivityInternal(filter, match, set, activity, true, userId);
10012 }
10013
10014 private void addPreferredActivityInternal(IntentFilter filter, int match,
10015 ComponentName[] set, ComponentName activity, boolean always, int userId) {
Kenny Root447106f2011-03-23 11:00:15 -070010016 // writer
Amith Yamasania3f133a2012-08-09 17:11:28 -070010017 int callingUid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -070010018 enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
Christopher Tatee202cad2013-10-29 17:42:26 -070010019 if (filter.countActions() == 0) {
10020 Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
10021 return;
10022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010024 if (mContext.checkCallingOrSelfPermission(
10025 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
10026 != PackageManager.PERMISSION_GRANTED) {
Amith Yamasania3f133a2012-08-09 17:11:28 -070010027 if (getUidTargetSdkVersionLockedLPr(callingUid)
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010028 < Build.VERSION_CODES.FROYO) {
10029 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
Amith Yamasania3f133a2012-08-09 17:11:28 -070010030 + callingUid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010031 return;
10032 }
10033 mContext.enforceCallingOrSelfPermission(
10034 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10035 }
Amith Yamasania3f133a2012-08-09 17:11:28 -070010036
10037 Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
Dianne Hackborn63092712012-10-07 14:45:35 -070010039 mSettings.editPreferredActivitiesLPw(userId).addFilter(
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010040 new PreferredActivity(filter, match, set, activity, always));
Dianne Hackborn63092712012-10-07 14:45:35 -070010041 mSettings.writePackageRestrictionsLPr(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 }
10043 }
10044
Satish Sampath8dbe6122009-06-02 23:35:54 +010010045 public void replacePreferredActivity(IntentFilter filter, int match,
10046 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +010010047 if (filter.countActions() != 1) {
10048 throw new IllegalArgumentException(
10049 "replacePreferredActivity expects filter to have only 1 action.");
10050 }
Satish Sampath8dbe6122009-06-02 23:35:54 +010010051 if (filter.countDataAuthorities() != 0
10052 || filter.countDataPaths() != 0
Christopher Tate087044c2013-11-11 17:43:43 -080010053 || filter.countDataSchemes() > 1
Satish Sampath8dbe6122009-06-02 23:35:54 +010010054 || filter.countDataTypes() != 0) {
10055 throw new IllegalArgumentException(
10056 "replacePreferredActivity expects filter to have no data authorities, " +
Christopher Tate087044c2013-11-11 17:43:43 -080010057 "paths, or types; and at most one scheme.");
Satish Sampath8dbe6122009-06-02 23:35:54 +010010058 }
10059 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010060 if (mContext.checkCallingOrSelfPermission(
10061 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
10062 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -070010063 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010064 < Build.VERSION_CODES.FROYO) {
10065 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
10066 + Binder.getCallingUid());
10067 return;
10068 }
10069 mContext.enforceCallingOrSelfPermission(
10070 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10071 }
Amith Yamasania3f133a2012-08-09 17:11:28 -070010072
10073 final int callingUserId = UserHandle.getCallingUserId();
Dianne Hackborn63092712012-10-07 14:45:35 -070010074 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(callingUserId);
10075 if (pir != null) {
Christopher Tate087044c2013-11-11 17:43:43 -080010076 Intent intent = new Intent(filter.getAction(0)).addCategory(filter.getCategory(0));
10077 if (filter.countDataSchemes() == 1) {
10078 Uri.Builder builder = new Uri.Builder();
10079 builder.scheme(filter.getDataScheme(0));
10080 intent.setData(builder.build());
Satish Sampath8dbe6122009-06-02 23:35:54 +010010081 }
Christopher Tate087044c2013-11-11 17:43:43 -080010082 List<PreferredActivity> matches = pir.queryIntent(
10083 intent, null, true, callingUserId);
10084 if (DEBUG_PREFERRED) {
10085 Slog.i(TAG, matches.size() + " preferred matches for " + intent);
10086 }
10087 for (int i = 0; i < matches.size(); i++) {
10088 PreferredActivity pa = matches.get(i);
10089 if (DEBUG_PREFERRED) {
10090 Slog.i(TAG, "Removing preferred activity "
10091 + pa.mPref.mComponent + ":");
10092 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
Dianne Hackborn63092712012-10-07 14:45:35 -070010093 }
Christopher Tate087044c2013-11-11 17:43:43 -080010094 pir.removeFilter(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -080010095 }
10096 }
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010097 addPreferredActivityInternal(filter, match, set, activity, true, callingUserId);
Satish Sampath8dbe6122009-06-02 23:35:54 +010010098 }
10099 }
10100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -070010102 final int uid = Binder.getCallingUid();
10103 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010104 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -080010105 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010106 if (pkg == null || pkg.applicationInfo.uid != uid) {
10107 if (mContext.checkCallingOrSelfPermission(
10108 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
10109 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -070010110 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010111 < Build.VERSION_CODES.FROYO) {
10112 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
10113 + Binder.getCallingUid());
10114 return;
10115 }
10116 mContext.enforceCallingOrSelfPermission(
10117 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10118 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -080010119 }
10120
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010121 int user = UserHandle.getCallingUserId();
10122 if (clearPackagePreferredActivitiesLPw(packageName, user)) {
10123 mSettings.writePackageRestrictionsLPr(user);
10124 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010125 }
10126 }
10127 }
10128
Amith Yamasania3f133a2012-08-09 17:11:28 -070010129 /** This method takes a specific user id as well as UserHandle.USER_ALL. */
10130 boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
Dianne Hackborn04505102012-02-29 12:34:04 -080010131 ArrayList<PreferredActivity> removed = null;
Dianne Hackborn63092712012-10-07 14:45:35 -070010132 boolean changed = false;
10133 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
10134 final int thisUserId = mSettings.mPreferredActivities.keyAt(i);
10135 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
10136 if (userId != UserHandle.USER_ALL && userId != thisUserId) {
Amith Yamasania3f133a2012-08-09 17:11:28 -070010137 continue;
10138 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010139 Iterator<PreferredActivity> it = pir.filterIterator();
10140 while (it.hasNext()) {
10141 PreferredActivity pa = it.next();
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010142 // Mark entry for removal only if it matches the package name
10143 // and the entry is of type "always".
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010144 if (packageName == null ||
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010145 (pa.mPref.mComponent.getPackageName().equals(packageName)
10146 && pa.mPref.mAlways)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010147 if (removed == null) {
10148 removed = new ArrayList<PreferredActivity>();
10149 }
10150 removed.add(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -080010151 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010152 }
10153 if (removed != null) {
10154 for (int j=0; j<removed.size(); j++) {
10155 PreferredActivity pa = removed.get(j);
10156 pir.removeFilter(pa);
10157 }
10158 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010159 }
10160 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010161 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010162 }
10163
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010164 public void resetPreferredActivities(int userId) {
10165 mContext.enforceCallingOrSelfPermission(
10166 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
10167 // writer
10168 synchronized (mPackages) {
10169 int user = UserHandle.getCallingUserId();
10170 clearPackagePreferredActivitiesLPw(null, user);
10171 mSettings.readDefaultPreferredAppsLPw(this, user);
10172 mSettings.writePackageRestrictionsLPr(user);
10173 scheduleWriteSettingsLocked();
10174 }
10175 }
10176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010177 public int getPreferredActivities(List<IntentFilter> outFilters,
10178 List<ComponentName> outActivities, String packageName) {
10179
10180 int num = 0;
Amith Yamasania3f133a2012-08-09 17:11:28 -070010181 final int userId = UserHandle.getCallingUserId();
Kenny Root447106f2011-03-23 11:00:15 -070010182 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010183 synchronized (mPackages) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010184 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
10185 if (pir != null) {
10186 final Iterator<PreferredActivity> it = pir.filterIterator();
10187 while (it.hasNext()) {
10188 final PreferredActivity pa = it.next();
10189 if (packageName == null
Amith Yamasanie9ecc8b2013-08-22 11:16:27 -070010190 || (pa.mPref.mComponent.getPackageName().equals(packageName)
10191 && pa.mPref.mAlways)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010192 if (outFilters != null) {
10193 outFilters.add(new IntentFilter(pa));
10194 }
10195 if (outActivities != null) {
10196 outActivities.add(pa.mPref.mComponent);
10197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 }
10199 }
10200 }
10201 }
10202
10203 return num;
10204 }
10205
Amith Yamasani483f3b02012-03-13 16:08:00 -070010206 @Override
Christopher Tatea2a0850d2013-09-05 16:38:58 -070010207 public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
10208 Intent intent = new Intent(Intent.ACTION_MAIN);
10209 intent.addCategory(Intent.CATEGORY_HOME);
10210
10211 final int callingUserId = UserHandle.getCallingUserId();
Christopher Tatebd413f62013-09-18 18:31:59 -070010212 List<ResolveInfo> list = queryIntentActivities(intent, null,
10213 PackageManager.GET_META_DATA, callingUserId);
Christopher Tatea2a0850d2013-09-05 16:38:58 -070010214 ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
Dianne Hackborn38ba6e92013-09-23 11:08:52 -070010215 true, false, false, callingUserId);
Christopher Tatea2a0850d2013-09-05 16:38:58 -070010216
10217 allHomeCandidates.clear();
10218 if (list != null) {
10219 for (ResolveInfo ri : list) {
10220 allHomeCandidates.add(ri);
10221 }
10222 }
10223 return (preferred == null || preferred.activityInfo == null)
10224 ? null
10225 : new ComponentName(preferred.activityInfo.packageName,
10226 preferred.activityInfo.name);
10227 }
10228
10229 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 public void setApplicationEnabledSetting(String appPackageName,
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010231 int newState, int flags, int userId, String callingPackage) {
Amith Yamasani13593602012-03-22 16:16:17 -070010232 if (!sUserManager.exists(userId)) return;
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010233 if (callingPackage == null) {
10234 callingPackage = Integer.toString(Binder.getCallingUid());
10235 }
10236 setEnabledSetting(appPackageName, null, newState, flags, userId, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 }
10238
Amith Yamasani483f3b02012-03-13 16:08:00 -070010239 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010240 public void setComponentEnabledSetting(ComponentName componentName,
Amith Yamasani483f3b02012-03-13 16:08:00 -070010241 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010242 if (!sUserManager.exists(userId)) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010243 setEnabledSetting(componentName.getPackageName(),
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010244 componentName.getClassName(), newState, flags, userId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 }
10246
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010247 private void setEnabledSetting(final String packageName, String className, int newState,
10248 final int flags, int userId, String callingPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
10250 || newState == COMPONENT_ENABLED_STATE_ENABLED
Dianne Hackborn0ac30312011-06-17 14:49:23 -070010251 || newState == COMPONENT_ENABLED_STATE_DISABLED
Dianne Hackbornfd7aded2013-01-22 17:10:23 -080010252 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER
10253 || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 throw new IllegalArgumentException("Invalid new component state: "
10255 + newState);
10256 }
10257 PackageSetting pkgSetting;
10258 final int uid = Binder.getCallingUid();
Dianne Hackbornfd7aded2013-01-22 17:10:23 -080010259 final int permission = mContext.checkCallingOrSelfPermission(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
Amith Yamasanif203aee2012-08-29 18:41:53 -070010261 enforceCrossUserPermission(uid, userId, false, "set enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010263 boolean sendNow = false;
10264 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010265 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010267 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -070010268
10269 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010270 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010271 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010273 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010275 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010276 }
10277 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010278 "Unknown component: " + packageName
10279 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 }
Amith Yamasani483f3b02012-03-13 16:08:00 -070010281 // Allow root and verify that userId is not being specified by a different user
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070010282 if (!allowedByPermission && !UserHandle.isSameApp(uid, pkgSetting.appId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010283 throw new SecurityException(
10284 "Permission Denial: attempt to change component state from pid="
10285 + Binder.getCallingPid()
Amith Yamasani13593602012-03-22 16:16:17 -070010286 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010288 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 // We're dealing with an application/package level state change
Amith Yamasani483f3b02012-03-13 16:08:00 -070010290 if (pkgSetting.getEnabled(userId) == newState) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010291 // Nothing to do
10292 return;
10293 }
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -070010294 if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
10295 || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
10296 // Don't care about who enables an app.
10297 callingPackage = null;
10298 }
10299 pkgSetting.setEnabled(newState, userId, callingPackage);
Amith Yamasani13593602012-03-22 16:16:17 -070010300 // pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 } else {
10302 // We're dealing with a component level state change
Dianne Hackborn65696252012-03-05 18:49:21 -080010303 // First, verify that this is a valid class name.
10304 PackageParser.Package pkg = pkgSetting.pkg;
10305 if (pkg == null || !pkg.hasComponentClassName(className)) {
10306 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
10307 throw new IllegalArgumentException("Component class " + className
10308 + " does not exist in " + packageName);
10309 } else {
10310 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
10311 + className + " does not exist in " + packageName);
10312 }
10313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 switch (newState) {
10315 case COMPONENT_ENABLED_STATE_ENABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -070010316 if (!pkgSetting.enableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010317 return;
10318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 break;
10320 case COMPONENT_ENABLED_STATE_DISABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -070010321 if (!pkgSetting.disableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010322 return;
10323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010324 break;
10325 case COMPONENT_ENABLED_STATE_DEFAULT:
Amith Yamasani483f3b02012-03-13 16:08:00 -070010326 if (!pkgSetting.restoreComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -070010327 return;
10328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 break;
10330 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010331 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010332 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 }
10334 }
Amith Yamasani483f3b02012-03-13 16:08:00 -070010335 mSettings.writePackageRestrictionsLPr(userId);
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010336 components = mPendingBroadcasts.get(userId, packageName);
Kenny Root447106f2011-03-23 11:00:15 -070010337 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010338 if (newPackage) {
10339 components = new ArrayList<String>();
10340 }
10341 if (!components.contains(componentName)) {
10342 components.add(componentName);
10343 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010344 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
10345 sendNow = true;
10346 // Purge entry from pending broadcast list if another one exists already
10347 // since we are sending one right away.
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010348 mPendingBroadcasts.remove(userId, packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010349 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010350 if (newPackage) {
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010351 mPendingBroadcasts.put(userId, packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010352 }
10353 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
10354 // Schedule a message
10355 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
10356 }
10357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 long callingId = Binder.clearCallingIdentity();
10361 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010362 if (sendNow) {
Christopher Tate1e08f5c2013-05-02 13:27:27 -070010363 packageUid = UserHandle.getUid(userId, pkgSetting.appId);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010364 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010365 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 } finally {
10368 Binder.restoreCallingIdentity(callingId);
10369 }
10370 }
10371
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010372 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010373 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -080010374 if (DEBUG_INSTALL)
10375 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
10376 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -080010377 Bundle extras = new Bundle(4);
10378 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
10379 String nameList[] = new String[componentNames.size()];
10380 componentNames.toArray(nameList);
10381 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010382 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
10383 extras.putInt(Intent.EXTRA_UID, packageUid);
Amith Yamasani13593602012-03-22 16:16:17 -070010384 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -070010385 new int[] {UserHandle.getUserId(packageUid)});
Dianne Hackborne7f97212011-02-24 14:40:20 -080010386 }
10387
Amith Yamasani483f3b02012-03-13 16:08:00 -070010388 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010389 if (!sUserManager.exists(userId)) return;
Dianne Hackborne7f97212011-02-24 14:40:20 -080010390 final int uid = Binder.getCallingUid();
10391 final int permission = mContext.checkCallingOrSelfPermission(
10392 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
10393 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Amith Yamasanif203aee2012-08-29 18:41:53 -070010394 enforceCrossUserPermission(uid, userId, true, "stop package");
Kenny Root447106f2011-03-23 11:00:15 -070010395 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -080010396 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -070010397 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
Amith Yamasani483f3b02012-03-13 16:08:00 -070010398 uid, userId)) {
10399 scheduleWritePackageRestrictionsLocked(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010400 }
10401 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070010402 }
10403
Jacek Surazski65e13172009-04-28 15:26:38 +020010404 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -070010405 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +020010406 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -070010407 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +020010408 }
10409 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010410
Amith Yamasani483f3b02012-03-13 16:08:00 -070010411 @Override
10412 public int getApplicationEnabledSetting(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010413 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -070010414 int uid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -070010415 enforceCrossUserPermission(uid, userId, false, "get enabled");
Kenny Root447106f2011-03-23 11:00:15 -070010416 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -070010418 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 }
10420 }
10421
Amith Yamasani483f3b02012-03-13 16:08:00 -070010422 @Override
10423 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -070010424 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -070010425 int uid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -070010426 enforceCrossUserPermission(uid, userId, false, "get component enabled");
Kenny Root447106f2011-03-23 11:00:15 -070010427 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -070010429 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 }
10431 }
10432
10433 public void enterSafeMode() {
Kenny Root461ff1f2011-08-09 09:43:03 -070010434 enforceSystemOrRoot("Only the system can request entering safe mode");
10435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 if (!mSystemReady) {
10437 mSafeMode = true;
10438 }
10439 }
10440
10441 public void systemReady() {
10442 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010443
10444 // Read the compatibilty setting when the system is ready.
Jeff Sharkey6e2bee72012-10-01 13:39:08 -070010445 boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010446 mContext.getContentResolver(),
Jeff Sharkey6e2bee72012-10-01 13:39:08 -070010447 android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -070010448 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010449 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -070010450 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -070010451 }
Dianne Hackborn63092712012-10-07 14:45:35 -070010452
10453 synchronized (mPackages) {
10454 // Verify that all of the preferred activity components actually
10455 // exist. It is possible for applications to be updated and at
10456 // that point remove a previously declared activity component that
10457 // had been set as a preferred activity. We try to clean this up
10458 // the next time we encounter that preferred activity, but it is
10459 // possible for the user flow to never be able to return to that
10460 // situation so here we do a sanity check to make sure we haven't
10461 // left any junk around.
10462 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
10463 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
10464 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
10465 removed.clear();
10466 for (PreferredActivity pa : pir.filterSet()) {
10467 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
10468 removed.add(pa);
10469 }
10470 }
10471 if (removed.size() > 0) {
10472 for (int j=0; j<removed.size(); j++) {
10473 PreferredActivity pa = removed.get(i);
Dianne Hackborn63092712012-10-07 14:45:35 -070010474 Slog.w(TAG, "Removing dangling preferred activity: "
Dianne Hackborn40e9f292012-11-27 19:12:23 -080010475 + pa.mPref.mComponent);
Dianne Hackborn63092712012-10-07 14:45:35 -070010476 pir.removeFilter(pa);
10477 }
10478 mSettings.writePackageRestrictionsLPr(
10479 mSettings.mPreferredActivities.keyAt(i));
10480 }
10481 }
10482 }
Amith Yamasani1a7472e2013-07-02 11:17:30 -070010483 sUserManager.systemReady();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 }
10485
10486 public boolean isSafeMode() {
10487 return mSafeMode;
10488 }
10489
10490 public boolean hasSystemUidErrors() {
10491 return mHasSystemUidErrors;
10492 }
10493
10494 static String arrayToString(int[] array) {
10495 StringBuffer buf = new StringBuffer(128);
10496 buf.append('[');
10497 if (array != null) {
10498 for (int i=0; i<array.length; i++) {
10499 if (i > 0) buf.append(", ");
10500 buf.append(array[i]);
10501 }
10502 }
10503 buf.append(']');
10504 return buf.toString();
10505 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010506
Kenny Root447106f2011-03-23 11:00:15 -070010507 static class DumpState {
10508 public static final int DUMP_LIBS = 1 << 0;
10509
10510 public static final int DUMP_FEATURES = 1 << 1;
10511
10512 public static final int DUMP_RESOLVERS = 1 << 2;
10513
10514 public static final int DUMP_PERMISSIONS = 1 << 3;
10515
10516 public static final int DUMP_PACKAGES = 1 << 4;
10517
10518 public static final int DUMP_SHARED_USERS = 1 << 5;
10519
10520 public static final int DUMP_MESSAGES = 1 << 6;
10521
10522 public static final int DUMP_PROVIDERS = 1 << 7;
10523
Kenny Root05ca4c92011-09-15 10:36:25 -070010524 public static final int DUMP_VERIFIERS = 1 << 8;
10525
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010526 public static final int DUMP_PREFERRED = 1 << 9;
10527
10528 public static final int DUMP_PREFERRED_XML = 1 << 10;
10529
Geremy Condraf1bcca82013-01-07 22:35:24 -080010530 public static final int DUMP_KEYSETS = 1 << 11;
10531
Kenny Root447106f2011-03-23 11:00:15 -070010532 public static final int OPTION_SHOW_FILTERS = 1 << 0;
10533
10534 private int mTypes;
10535
10536 private int mOptions;
10537
10538 private boolean mTitlePrinted;
10539
10540 private SharedUserSetting mSharedUser;
10541
10542 public boolean isDumping(int type) {
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010543 if (mTypes == 0 && type != DUMP_PREFERRED_XML) {
Kenny Root447106f2011-03-23 11:00:15 -070010544 return true;
10545 }
10546
10547 return (mTypes & type) != 0;
10548 }
10549
10550 public void setDump(int type) {
10551 mTypes |= type;
10552 }
10553
10554 public boolean isOptionEnabled(int option) {
10555 return (mOptions & option) != 0;
10556 }
10557
10558 public void setOptionEnabled(int option) {
10559 mOptions |= option;
10560 }
10561
10562 public boolean onTitlePrinted() {
10563 final boolean printed = mTitlePrinted;
10564 mTitlePrinted = true;
10565 return printed;
10566 }
10567
10568 public boolean getTitlePrinted() {
10569 return mTitlePrinted;
10570 }
10571
10572 public void setTitlePrinted(boolean enabled) {
10573 mTitlePrinted = enabled;
10574 }
10575
10576 public SharedUserSetting getSharedUser() {
10577 return mSharedUser;
10578 }
10579
10580 public void setSharedUser(SharedUserSetting user) {
10581 mSharedUser = user;
10582 }
10583 }
10584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 @Override
10586 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10587 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
10588 != PackageManager.PERMISSION_GRANTED) {
10589 pw.println("Permission Denial: can't dump ActivityManager from from pid="
10590 + Binder.getCallingPid()
10591 + ", uid=" + Binder.getCallingUid()
10592 + " without permission "
10593 + android.Manifest.permission.DUMP);
10594 return;
10595 }
10596
Kenny Root447106f2011-03-23 11:00:15 -070010597 DumpState dumpState = new DumpState();
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010598 boolean fullPreferred = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010599
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010600 String packageName = null;
10601
10602 int opti = 0;
10603 while (opti < args.length) {
10604 String opt = args[opti];
10605 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10606 break;
10607 }
10608 opti++;
10609 if ("-a".equals(opt)) {
10610 // Right now we only know how to print all.
10611 } else if ("-h".equals(opt)) {
10612 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010613 pw.println(" [-h] [-f] [cmd] ...");
10614 pw.println(" -f: print details of intent filters");
10615 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010616 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010617 pw.println(" l[ibraries]: list known shared libraries");
10618 pw.println(" f[ibraries]: list device features");
10619 pw.println(" r[esolvers]: dump intent resolvers");
10620 pw.println(" perm[issions]: dump permissions");
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010621 pw.println(" pref[erred]: print preferred package settings");
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010622 pw.println(" preferred-xml [--full]: print preferred package settings as xml");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010623 pw.println(" prov[iders]: dump content providers");
10624 pw.println(" p[ackages]: dump installed packages");
10625 pw.println(" s[hared-users]: dump shared user IDs");
10626 pw.println(" m[essages]: print collected runtime messages");
Kenny Root05ca4c92011-09-15 10:36:25 -070010627 pw.println(" v[erifiers]: print package verifier info");
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010628 pw.println(" <package.name>: info about given package");
Geremy Condraf1bcca82013-01-07 22:35:24 -080010629 pw.println(" k[eysets]: print known keysets");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010630 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010631 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -070010632 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010633 } else {
10634 pw.println("Unknown argument: " + opt + "; use -h for help");
10635 }
10636 }
10637
10638 // Is the caller requesting to dump a particular piece of data?
10639 if (opti < args.length) {
10640 String cmd = args[opti];
10641 opti++;
10642 // Is this a package name?
10643 if ("android".equals(cmd) || cmd.contains(".")) {
10644 packageName = cmd;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010645 // When dumping a single package, we always dump all of its
10646 // filter information since the amount of data will be reasonable.
10647 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010648 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010649 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010650 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010651 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010652 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010653 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010654 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010655 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010656 } else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
10657 dumpState.setDump(DumpState.DUMP_PREFERRED);
10658 } else if ("preferred-xml".equals(cmd)) {
10659 dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010660 if (opti < args.length && "--full".equals(args[opti])) {
10661 fullPreferred = true;
Dianne Hackbornd4d93642013-01-29 16:12:48 -080010662 opti++;
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010663 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010664 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010665 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010666 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010667 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010668 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010669 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010670 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -070010671 dumpState.setDump(DumpState.DUMP_MESSAGES);
Kenny Root05ca4c92011-09-15 10:36:25 -070010672 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
10673 dumpState.setDump(DumpState.DUMP_VERIFIERS);
Geremy Condraf1bcca82013-01-07 22:35:24 -080010674 } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
10675 dumpState.setDump(DumpState.DUMP_KEYSETS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010676 }
10677 }
Kenny Root447106f2011-03-23 11:00:15 -070010678
10679 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010680 synchronized (mPackages) {
Kenny Root05ca4c92011-09-15 10:36:25 -070010681 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
10682 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010683 pw.println();
Kenny Root05ca4c92011-09-15 10:36:25 -070010684 pw.println("Verifiers:");
10685 pw.print(" Required: ");
10686 pw.print(mRequiredVerifierPackage);
10687 pw.print(" (uid=");
Amith Yamasani483f3b02012-03-13 16:08:00 -070010688 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
Kenny Root05ca4c92011-09-15 10:36:25 -070010689 pw.println(")");
10690 }
10691
Kenny Root447106f2011-03-23 11:00:15 -070010692 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010693 boolean printedHeader = false;
Kenny Root447106f2011-03-23 11:00:15 -070010694 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010695 while (it.hasNext()) {
10696 String name = it.next();
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010697 SharedLibraryEntry ent = mSharedLibraries.get(name);
10698 if (!printedHeader) {
10699 if (dumpState.onTitlePrinted())
10700 pw.println();
10701 pw.println("Libraries:");
10702 printedHeader = true;
10703 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010704 pw.print(" ");
10705 pw.print(name);
10706 pw.print(" -> ");
Dianne Hackbornc895be72013-03-11 17:48:43 -070010707 if (ent.path != null) {
10708 pw.print("(jar) ");
10709 pw.print(ent.path);
10710 } else {
10711 pw.print("(apk) ");
10712 pw.print(ent.apk);
10713 }
10714 pw.println();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010715 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010716 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010717
Kenny Root447106f2011-03-23 11:00:15 -070010718 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
10719 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010720 pw.println();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010721 pw.println("Features:");
10722 Iterator<String> it = mAvailableFeatures.keySet().iterator();
10723 while (it.hasNext()) {
10724 String name = it.next();
10725 pw.print(" ");
10726 pw.println(name);
10727 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010728 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010729
Kenny Root447106f2011-03-23 11:00:15 -070010730 if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
10731 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
10732 : "Activity Resolver Table:", " ", packageName,
10733 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10734 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010735 }
Kenny Root447106f2011-03-23 11:00:15 -070010736 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
10737 : "Receiver Resolver Table:", " ", packageName,
10738 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10739 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010740 }
Kenny Root447106f2011-03-23 11:00:15 -070010741 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
10742 : "Service Resolver Table:", " ", packageName,
10743 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10744 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010745 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -070010746 if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
10747 : "Provider Resolver Table:", " ", packageName,
10748 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
10749 dumpState.setTitlePrinted(true);
10750 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010751 }
10752
10753 if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010754 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
10755 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
10756 int user = mSettings.mPreferredActivities.keyAt(i);
10757 if (pir.dump(pw,
10758 dumpState.getTitlePrinted()
10759 ? "\nPreferred Activities User " + user + ":"
10760 : "Preferred Activities User " + user + ":", " ",
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070010761 packageName, true)) {
Dianne Hackborn63092712012-10-07 14:45:35 -070010762 dumpState.setTitlePrinted(true);
10763 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010764 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010765 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010766
10767 if (dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
10768 pw.flush();
10769 FileOutputStream fout = new FileOutputStream(fd);
10770 BufferedOutputStream str = new BufferedOutputStream(fout);
10771 XmlSerializer serializer = new FastXmlSerializer();
10772 try {
10773 serializer.setOutput(str, "utf-8");
10774 serializer.startDocument(null, true);
10775 serializer.setFeature(
10776 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010777 mSettings.writePreferredActivitiesLPr(serializer, 0, fullPreferred);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070010778 serializer.endDocument();
10779 serializer.flush();
10780 } catch (IllegalArgumentException e) {
10781 pw.println("Failed writing: " + e);
10782 } catch (IllegalStateException e) {
10783 pw.println("Failed writing: " + e);
10784 } catch (IOException e) {
10785 pw.println("Failed writing: " + e);
10786 }
10787 }
10788
Kenny Root447106f2011-03-23 11:00:15 -070010789 if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
10790 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010792
Kenny Root447106f2011-03-23 11:00:15 -070010793 if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
10794 boolean printedSomething = false;
Jeff Sharkey85f5f812013-10-07 10:16:12 -070010795 for (PackageParser.Provider p : mProviders.mProviders.values()) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010796 if (packageName != null && !packageName.equals(p.info.packageName)) {
10797 continue;
10798 }
10799 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -070010800 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010801 pw.println();
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010802 pw.println("Registered ContentProviders:");
10803 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010804 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070010805 pw.print(" "); p.printComponentShortName(pw); pw.println(":");
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010806 pw.print(" "); pw.println(p.toString());
10807 }
10808 printedSomething = false;
Jeff Sharkey85f5f812013-10-07 10:16:12 -070010809 for (Map.Entry<String, PackageParser.Provider> entry :
10810 mProvidersByAuthority.entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010811 PackageParser.Provider p = entry.getValue();
10812 if (packageName != null && !packageName.equals(p.info.packageName)) {
10813 continue;
10814 }
10815 if (!printedSomething) {
10816 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010817 pw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -080010818 pw.println("ContentProvider Authorities:");
10819 printedSomething = true;
10820 }
10821 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
10822 pw.print(" "); pw.println(p.toString());
Kenny Rooteca64b32012-06-25 16:37:32 -070010823 if (p.info != null && p.info.applicationInfo != null) {
10824 final String appInfo = p.info.applicationInfo.toString();
10825 pw.print(" applicationInfo="); pw.println(appInfo);
10826 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010827 }
10828 }
Geremy Condraf1bcca82013-01-07 22:35:24 -080010829
10830 if (dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010831 mSettings.mKeySetManager.dump(pw, packageName, dumpState);
Geremy Condraf1bcca82013-01-07 22:35:24 -080010832 }
10833
Kenny Root447106f2011-03-23 11:00:15 -070010834 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
10835 mSettings.dumpPackagesLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 }
Kenny Root447106f2011-03-23 11:00:15 -070010837
10838 if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
10839 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -080010840 }
Kenny Root447106f2011-03-23 11:00:15 -070010841
10842 if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
10843 if (dumpState.onTitlePrinted())
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010844 pw.println();
Kenny Root447106f2011-03-23 11:00:15 -070010845 mSettings.dumpReadMessagesLPr(pw, dumpState);
10846
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070010847 pw.println();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010848 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -070010849 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -080010850 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010851 try {
10852 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -070010853 final int avail = in.available();
10854 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010855 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -070010856 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010857 } catch (FileNotFoundException e) {
10858 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -080010859 } finally {
10860 if (in != null) {
10861 try {
10862 in.close();
Kenny Root447106f2011-03-23 11:00:15 -070010863 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -080010864 }
10865 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010866 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -080010867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010868 }
10869 }
10870
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010871 // ------- apps on sdcard specific code -------
10872 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -070010873
Kenny Root305bcbf2010-09-03 07:56:38 -070010874 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -070010875
Kenny Root305bcbf2010-09-03 07:56:38 -070010876 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -070010877
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080010878 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010879
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010880 private String getEncryptKey() {
10881 try {
Kenny Root305bcbf2010-09-03 07:56:38 -070010882 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
10883 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010884 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -070010885 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
10886 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010887 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010888 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010889 return null;
10890 }
10891 }
10892 return sdEncKey;
10893 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010894 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010895 return null;
Rich Cannings8d578832010-09-09 15:12:40 -070010896 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -070010897 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -070010898 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010899 }
Rich Cannings8d578832010-09-09 15:12:40 -070010900
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010901 }
10902
Kenny Root447106f2011-03-23 11:00:15 -070010903 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -070010904 int tmpIdx = 1;
10905 String list[] = PackageHelper.getSecureContainerList();
10906 if (list != null) {
10907 for (final String name : list) {
10908 // Ignore null and non-temporary container entries
10909 if (name == null || !name.startsWith(mTempContainerPrefix)) {
10910 continue;
10911 }
10912
10913 String subStr = name.substring(mTempContainerPrefix.length());
10914 try {
10915 int cid = Integer.parseInt(subStr);
10916 if (cid >= tmpIdx) {
10917 tmpIdx = cid + 1;
10918 }
10919 } catch (NumberFormatException e) {
10920 }
10921 }
10922 }
10923 return mTempContainerPrefix + tmpIdx;
10924 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010925
Kenny Root447106f2011-03-23 11:00:15 -070010926 /*
10927 * Update media status on PackageManager.
10928 */
10929 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
10930 int callingUid = Binder.getCallingUid();
10931 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
10932 throw new SecurityException("Media status can only be updated by the system");
10933 }
10934 // reader; this apparently protects mMediaMounted, but should probably
10935 // be a different lock in that case.
10936 synchronized (mPackages) {
10937 Log.i(TAG, "Updating external media status from "
10938 + (mMediaMounted ? "mounted" : "unmounted") + " to "
10939 + (mediaStatus ? "mounted" : "unmounted"));
10940 if (DEBUG_SD_INSTALL)
10941 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
10942 + ", mMediaMounted=" + mMediaMounted);
10943 if (mediaStatus == mMediaMounted) {
10944 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
10945 : 0, -1);
10946 mHandler.sendMessage(msg);
10947 return;
10948 }
10949 mMediaMounted = mediaStatus;
10950 }
10951 // Queue up an async operation since the package installation may take a
10952 // little while.
10953 mHandler.post(new Runnable() {
10954 public void run() {
Kenny Root438a0ef2012-08-09 13:36:16 -070010955 updateExternalMediaStatusInner(mediaStatus, reportStatus, true);
Kenny Root447106f2011-03-23 11:00:15 -070010956 }
10957 });
10958 }
10959
Kenny Root51a573c2012-05-17 13:30:28 -070010960 /**
10961 * Called by MountService when the initial ASECs to scan are available.
10962 * Should block until all the ASEC containers are finished being scanned.
10963 */
10964 public void scanAvailableAsecs() {
Kenny Root438a0ef2012-08-09 13:36:16 -070010965 updateExternalMediaStatusInner(true, false, false);
Kenny Root51a573c2012-05-17 13:30:28 -070010966 }
10967
Kenny Root447106f2011-03-23 11:00:15 -070010968 /*
10969 * Collect information of applications on external media, map them against
10970 * existing containers and update information based on current mount status.
10971 * Please note that we always have to report status if reportStatus has been
10972 * set to true especially when unloading packages.
10973 */
Kenny Root438a0ef2012-08-09 13:36:16 -070010974 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus,
10975 boolean externalStorage) {
Kenny Root447106f2011-03-23 11:00:15 -070010976 // Collection of uids
10977 int uidArr[] = null;
10978 // Collection of stale containers
10979 HashSet<String> removeCids = new HashSet<String>();
10980 // Collection of packages on external media with valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -070010981 HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
Kenny Root447106f2011-03-23 11:00:15 -070010982 // Get list of secure containers.
10983 final String list[] = PackageHelper.getSecureContainerList();
10984 if (list == null || list.length == 0) {
10985 Log.i(TAG, "No secure containers on sdcard");
10986 } else {
10987 // Process list of secure containers and categorize them
10988 // as active or stale based on their package internal state.
10989 int uidList[] = new int[list.length];
10990 int num = 0;
10991 // reader
10992 synchronized (mPackages) {
10993 for (String cid : list) {
Kenny Root447106f2011-03-23 11:00:15 -070010994 if (DEBUG_SD_INSTALL)
10995 Log.i(TAG, "Processing container " + cid);
Kenny Rootc7a89992012-06-05 15:13:17 -070010996 String pkgName = getAsecPackageName(cid);
Kenny Root447106f2011-03-23 11:00:15 -070010997 if (pkgName == null) {
10998 if (DEBUG_SD_INSTALL)
10999 Log.i(TAG, "Container : " + cid + " stale");
11000 removeCids.add(cid);
11001 continue;
11002 }
11003 if (DEBUG_SD_INSTALL)
11004 Log.i(TAG, "Looking for pkg : " + pkgName);
Kenny Rootc7a89992012-06-05 15:13:17 -070011005
11006 final PackageSetting ps = mSettings.mPackages.get(pkgName);
11007 if (ps == null) {
11008 Log.i(TAG, "Deleting container with no matching settings " + cid);
11009 removeCids.add(cid);
11010 continue;
11011 }
11012
Kenny Root438a0ef2012-08-09 13:36:16 -070011013 /*
11014 * Skip packages that are not external if we're unmounting
11015 * external storage.
11016 */
11017 if (externalStorage && !isMounted && !isExternal(ps)) {
11018 continue;
11019 }
11020
Kenny Rootc7a89992012-06-05 15:13:17 -070011021 final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
Kenny Root447106f2011-03-23 11:00:15 -070011022 // The package status is changed only if the code path
11023 // matches between settings and the container id.
Kenny Rootc7a89992012-06-05 15:13:17 -070011024 if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
11025 if (DEBUG_SD_INSTALL) {
Kenny Root447106f2011-03-23 11:00:15 -070011026 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
11027 + " at code path: " + ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -070011028 }
11029
Kenny Root447106f2011-03-23 11:00:15 -070011030 // We do have a valid package installed on sdcard
11031 processCids.put(args, ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -070011032 final int uid = ps.appId;
Kenny Root447106f2011-03-23 11:00:15 -070011033 if (uid != -1) {
11034 uidList[num++] = uid;
11035 }
11036 } else {
Kenny Rootc7a89992012-06-05 15:13:17 -070011037 Log.i(TAG, "Deleting stale container for " + cid);
Kenny Root447106f2011-03-23 11:00:15 -070011038 removeCids.add(cid);
11039 }
11040 }
11041 }
11042
11043 if (num > 0) {
11044 // Sort uid list
11045 Arrays.sort(uidList, 0, num);
11046 // Throw away duplicates
11047 uidArr = new int[num];
11048 uidArr[0] = uidList[0];
11049 int di = 0;
11050 for (int i = 1; i < num; i++) {
11051 if (uidList[i - 1] != uidList[i]) {
11052 uidArr[di++] = uidList[i];
11053 }
11054 }
11055 }
11056 }
11057 // Process packages with valid entries.
Kenny Root6dceb882012-04-12 14:23:49 -070011058 if (isMounted) {
Kenny Root447106f2011-03-23 11:00:15 -070011059 if (DEBUG_SD_INSTALL)
11060 Log.i(TAG, "Loading packages");
11061 loadMediaPackages(processCids, uidArr, removeCids);
Jeff Sharkey752cd922012-09-23 16:25:12 -070011062 startCleaningPackages();
Kenny Root447106f2011-03-23 11:00:15 -070011063 } else {
11064 if (DEBUG_SD_INSTALL)
11065 Log.i(TAG, "Unloading packages");
11066 unloadMediaPackages(processCids, uidArr, reportStatus);
11067 }
11068 }
11069
Christopher Tated15967482013-10-04 13:57:22 -070011070 private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
11071 ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
Kenny Root447106f2011-03-23 11:00:15 -070011072 int size = pkgList.size();
11073 if (size > 0) {
11074 // Send broadcasts here
11075 Bundle extras = new Bundle();
11076 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
11077 .toArray(new String[size]));
11078 if (uidArr != null) {
11079 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
11080 }
Christopher Tated15967482013-10-04 13:57:22 -070011081 if (replacing && !mediaStatus) {
11082 extras.putBoolean(Intent.EXTRA_REPLACING, replacing);
11083 }
Kenny Root447106f2011-03-23 11:00:15 -070011084 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
11085 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Dianne Hackborn7767eac2012-08-23 18:25:40 -070011086 sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
Kenny Root447106f2011-03-23 11:00:15 -070011087 }
11088 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011089
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070011090 /*
Kenny Root447106f2011-03-23 11:00:15 -070011091 * Look at potentially valid container ids from processCids If package
11092 * information doesn't match the one on record or package scanning fails,
11093 * the cid is added to list of removeCids. We currently don't delete stale
11094 * containers.
11095 */
Kenny Root6dceb882012-04-12 14:23:49 -070011096 private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -070011097 HashSet<String> removeCids) {
11098 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -070011099 Set<AsecInstallArgs> keys = processCids.keySet();
Kenny Root447106f2011-03-23 11:00:15 -070011100 boolean doGc = false;
Kenny Root6dceb882012-04-12 14:23:49 -070011101 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -070011102 String codePath = processCids.get(args);
11103 if (DEBUG_SD_INSTALL)
11104 Log.i(TAG, "Loading container : " + args.cid);
11105 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
11106 try {
11107 // Make sure there are no container errors first.
11108 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
11109 Slog.e(TAG, "Failed to mount cid : " + args.cid
11110 + " when installing from sdcard");
11111 continue;
11112 }
11113 // Check code path here.
11114 if (codePath == null || !codePath.equals(args.getCodePath())) {
11115 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
11116 + " does not match one in settings " + codePath);
11117 continue;
11118 }
11119 // Parse package
Kenny Root51a573c2012-05-17 13:30:28 -070011120 int parseFlags = mDefParseFlags;
11121 if (args.isExternal()) {
11122 parseFlags |= PackageParser.PARSE_ON_SDCARD;
11123 }
Kenny Rootc7a89992012-06-05 15:13:17 -070011124 if (args.isFwdLocked()) {
11125 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
11126 }
Kenny Root51a573c2012-05-17 13:30:28 -070011127
Kenny Root447106f2011-03-23 11:00:15 -070011128 doGc = true;
11129 synchronized (mInstallLock) {
11130 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -070011131 0, 0, null);
Kenny Root447106f2011-03-23 11:00:15 -070011132 // Scan the package
11133 if (pkg != null) {
11134 /*
11135 * TODO why is the lock being held? doPostInstall is
11136 * called in other places without the lock. This needs
11137 * to be straightened out.
11138 */
11139 // writer
11140 synchronized (mPackages) {
11141 retCode = PackageManager.INSTALL_SUCCEEDED;
11142 pkgList.add(pkg.packageName);
11143 // Post process args
Kenny Root6dceb882012-04-12 14:23:49 -070011144 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
11145 pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -070011146 }
11147 } else {
11148 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
11149 }
11150 }
11151
11152 } finally {
11153 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
11154 // Don't destroy container here. Wait till gc clears things
11155 // up.
11156 removeCids.add(args.cid);
11157 }
11158 }
11159 }
11160 // writer
11161 synchronized (mPackages) {
11162 // If the platform SDK has changed since the last time we booted,
11163 // we need to re-grant app permission to catch any new ones that
11164 // appear. This is really a hack, and means that apps can in some
11165 // cases get permissions that the user didn't initially explicitly
11166 // allow... it would be nice to have some better way to handle
11167 // this situation.
11168 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
11169 if (regrantPermissions)
11170 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
11171 + mSdkVersion + "; regranting permissions for external storage");
11172 mSettings.mExternalSdkPlatform = mSdkVersion;
11173
11174 // Make sure group IDs have been assigned, and any permission
11175 // changes in other apps are accounted for
Dianne Hackborne639da72012-02-21 15:11:13 -080011176 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
11177 | (regrantPermissions
11178 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
11179 : 0));
Kenny Root447106f2011-03-23 11:00:15 -070011180 // can downgrade to reader
11181 // Persist settings
11182 mSettings.writeLPr();
11183 }
11184 // Send a broadcast to let everyone know we are done processing
11185 if (pkgList.size() > 0) {
Christopher Tated15967482013-10-04 13:57:22 -070011186 sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null);
Kenny Root447106f2011-03-23 11:00:15 -070011187 }
11188 // Force gc to avoid any stale parser references that we might have.
11189 if (doGc) {
11190 Runtime.getRuntime().gc();
11191 }
11192 // List stale containers and destroy stale temporary containers.
11193 if (removeCids != null) {
11194 for (String cid : removeCids) {
11195 if (cid.startsWith(mTempContainerPrefix)) {
11196 Log.i(TAG, "Destroying stale temporary container " + cid);
11197 PackageHelper.destroySdDir(cid);
11198 } else {
11199 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080011200 }
11201 }
Kenny Root447106f2011-03-23 11:00:15 -070011202 }
11203 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011204
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080011205 /*
Kenny Root447106f2011-03-23 11:00:15 -070011206 * Utility method to unload a list of specified containers
11207 */
Kenny Root6dceb882012-04-12 14:23:49 -070011208 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -070011209 // Just unmount all valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -070011210 for (AsecInstallArgs arg : cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -070011211 synchronized (mInstallLock) {
11212 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080011213 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011214 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011215 }
11216
Kenny Root447106f2011-03-23 11:00:15 -070011217 /*
11218 * Unload packages mounted on external media. This involves deleting package
11219 * data from internal structures, sending broadcasts about diabled packages,
11220 * gc'ing to free up references, unmounting all secure containers
11221 * corresponding to packages on external media, and posting a
11222 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
11223 * that we always have to post this message if status has been requested no
11224 * matter what.
11225 */
Kenny Root6dceb882012-04-12 14:23:49 -070011226 private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -070011227 final boolean reportStatus) {
11228 if (DEBUG_SD_INSTALL)
11229 Log.i(TAG, "unloading media packages");
11230 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -070011231 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
11232 final Set<AsecInstallArgs> keys = processCids.keySet();
11233 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -070011234 String pkgName = args.getPackageName();
11235 if (DEBUG_SD_INSTALL)
11236 Log.i(TAG, "Trying to unload pkg : " + pkgName);
11237 // Delete package internally
11238 PackageRemovedInfo outInfo = new PackageRemovedInfo();
11239 synchronized (mInstallLock) {
Christopher Tateacee6e92013-05-14 16:11:44 -070011240 boolean res = deletePackageLI(pkgName, null, false, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -070011241 PackageManager.DELETE_KEEP_DATA, outInfo, false);
Kenny Root447106f2011-03-23 11:00:15 -070011242 if (res) {
11243 pkgList.add(pkgName);
11244 } else {
11245 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
11246 failedList.add(args);
11247 }
11248 }
11249 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070011250
Kenny Root447106f2011-03-23 11:00:15 -070011251 // reader
11252 synchronized (mPackages) {
11253 // We didn't update the settings after removing each package;
11254 // write them now for all packages.
11255 mSettings.writeLPr();
11256 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070011257
Kenny Root447106f2011-03-23 11:00:15 -070011258 // We have to absolutely send UPDATED_MEDIA_STATUS only
11259 // after confirming that all the receivers processed the ordered
11260 // broadcast when packages get disabled, force a gc to clean things up.
11261 // and unload all the containers.
11262 if (pkgList.size() > 0) {
Christopher Tated15967482013-10-04 13:57:22 -070011263 sendResourcesChangedBroadcast(false, false, pkgList, uidArr,
11264 new IIntentReceiver.Stub() {
Kenny Root447106f2011-03-23 11:00:15 -070011265 public void performReceive(Intent intent, int resultCode, String data,
Dianne Hackborn20e80982012-08-31 19:00:44 -070011266 Bundle extras, boolean ordered, boolean sticky,
11267 int sendingUser) throws RemoteException {
Kenny Root447106f2011-03-23 11:00:15 -070011268 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
11269 reportStatus ? 1 : 0, 1, keys);
11270 mHandler.sendMessage(msg);
11271 }
11272 });
11273 } else {
11274 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
11275 keys);
11276 mHandler.sendMessage(msg);
11277 }
11278 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070011279
Amith Yamasani6ec10122012-08-23 13:49:25 -070011280 /** Binder call */
11281 @Override
Kenny Root447106f2011-03-23 11:00:15 -070011282 public void movePackage(final String packageName, final IPackageMoveObserver observer,
11283 final int flags) {
11284 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
Amith Yamasani6ec10122012-08-23 13:49:25 -070011285 UserHandle user = new UserHandle(UserHandle.getCallingUserId());
Kenny Root447106f2011-03-23 11:00:15 -070011286 int returnCode = PackageManager.MOVE_SUCCEEDED;
11287 int currFlags = 0;
11288 int newFlags = 0;
11289 // reader
11290 synchronized (mPackages) {
11291 PackageParser.Package pkg = mPackages.get(packageName);
11292 if (pkg == null) {
11293 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
11294 } else {
11295 // Disable moving fwd locked apps and system packages
11296 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
11297 Slog.w(TAG, "Cannot move system application");
11298 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root447106f2011-03-23 11:00:15 -070011299 } else if (pkg.mOperationPending) {
11300 Slog.w(TAG, "Attempt to move package which has pending operations");
11301 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
11302 } else {
11303 // Find install location first
11304 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
11305 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
11306 Slog.w(TAG, "Ambigous flags specified for move location.");
11307 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
11308 } else {
11309 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
11310 : PackageManager.INSTALL_INTERNAL;
11311 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
11312 : PackageManager.INSTALL_INTERNAL;
Kenny Rootbf023582012-05-02 16:56:15 -070011313
Kenny Root447106f2011-03-23 11:00:15 -070011314 if (newFlags == currFlags) {
11315 Slog.w(TAG, "No move required. Trying to move to same location");
11316 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Rootbf023582012-05-02 16:56:15 -070011317 } else {
11318 if (isForwardLocked(pkg)) {
11319 currFlags |= PackageManager.INSTALL_FORWARD_LOCK;
11320 newFlags |= PackageManager.INSTALL_FORWARD_LOCK;
11321 }
Kenny Root447106f2011-03-23 11:00:15 -070011322 }
11323 }
11324 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
11325 pkg.mOperationPending = true;
11326 }
11327 }
11328 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080011329
Kenny Root447106f2011-03-23 11:00:15 -070011330 /*
11331 * TODO this next block probably shouldn't be inside the lock. We
11332 * can't guarantee these won't change after this is fired off
11333 * anyway.
11334 */
11335 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Amith Yamasani6ec10122012-08-23 13:49:25 -070011336 processPendingMove(new MoveParams(null, observer, 0, packageName,
11337 null, -1, user),
Kenny Root6dceb882012-04-12 14:23:49 -070011338 returnCode);
Kenny Root447106f2011-03-23 11:00:15 -070011339 } else {
11340 Message msg = mHandler.obtainMessage(INIT_COPY);
11341 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -070011342 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -070011343 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Amith Yamasani6ec10122012-08-23 13:49:25 -070011344 pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user);
Kenny Root447106f2011-03-23 11:00:15 -070011345 msg.obj = mp;
11346 mHandler.sendMessage(msg);
11347 }
11348 }
11349 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080011350
Kenny Root447106f2011-03-23 11:00:15 -070011351 private void processPendingMove(final MoveParams mp, final int currentStatus) {
11352 // Queue up an async operation since the package deletion may take a
11353 // little while.
11354 mHandler.post(new Runnable() {
11355 public void run() {
11356 // TODO fix this; this does nothing.
11357 mHandler.removeCallbacks(this);
11358 int returnCode = currentStatus;
11359 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
11360 int uidArr[] = null;
11361 ArrayList<String> pkgList = null;
11362 synchronized (mPackages) {
11363 PackageParser.Package pkg = mPackages.get(mp.packageName);
11364 if (pkg == null) {
11365 Slog.w(TAG, " Package " + mp.packageName
11366 + " doesn't exist. Aborting move");
11367 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
11368 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
11369 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
11370 + mp.srcArgs.getCodePath() + " to "
11371 + pkg.applicationInfo.sourceDir
11372 + " Aborting move and returning error");
11373 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
11374 } else {
11375 uidArr = new int[] {
11376 pkg.applicationInfo.uid
11377 };
11378 pkgList = new ArrayList<String>();
11379 pkgList.add(mp.packageName);
11380 }
11381 }
11382 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
11383 // Send resources unavailable broadcast
Christopher Tated15967482013-10-04 13:57:22 -070011384 sendResourcesChangedBroadcast(false, true, pkgList, uidArr, null);
Kenny Root447106f2011-03-23 11:00:15 -070011385 // Update package code and resource paths
11386 synchronized (mInstallLock) {
11387 synchronized (mPackages) {
11388 PackageParser.Package pkg = mPackages.get(mp.packageName);
11389 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -070011390 if (pkg == null) {
11391 Slog.w(TAG, " Package " + mp.packageName
11392 + " doesn't exist. Aborting move");
11393 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -070011394 } else if (!mp.srcArgs.getCodePath().equals(
11395 pkg.applicationInfo.sourceDir)) {
11396 Slog.w(TAG, "Package " + mp.packageName
11397 + " code path changed from " + mp.srcArgs.getCodePath()
11398 + " to " + pkg.applicationInfo.sourceDir
11399 + " Aborting move and returning error");
11400 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
11401 } else {
11402 final String oldCodePath = pkg.mPath;
11403 final String newCodePath = mp.targetArgs.getCodePath();
11404 final String newResPath = mp.targetArgs.getResourcePath();
11405 final String newNativePath = mp.targetArgs
11406 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -070011407
Kenny Rootddbe50d2012-09-06 13:18:37 -070011408 final File newNativeDir = new File(newNativePath);
Kenny Rootbf023582012-05-02 16:56:15 -070011409
Kenny Rootddbe50d2012-09-06 13:18:37 -070011410 if (!isForwardLocked(pkg) && !isExternal(pkg)) {
Kenny Roota3e90792012-10-18 10:58:36 -070011411 NativeLibraryHelper.copyNativeBinariesIfNeededLI(
11412 new File(newCodePath), newNativeDir);
11413 }
11414 final int[] users = sUserManager.getUserIds();
11415 for (int user : users) {
11416 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
11417 newNativePath, user) < 0) {
11418 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
Kenny Rootddbe50d2012-09-06 13:18:37 -070011419 }
Kenny Root6a6b0072010-10-07 16:46:10 -070011420 }
11421
11422 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
11423 pkg.mPath = newCodePath;
11424 // Move dex files around
11425 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
11426 // Moving of dex files failed. Set
11427 // error code and abort move.
11428 pkg.mPath = pkg.mScanPath;
11429 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
11430 }
11431 }
11432
11433 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -070011434 pkg.mScanPath = newCodePath;
11435 pkg.applicationInfo.sourceDir = newCodePath;
11436 pkg.applicationInfo.publicSourceDir = newResPath;
11437 pkg.applicationInfo.nativeLibraryDir = newNativePath;
11438 PackageSetting ps = (PackageSetting) pkg.mExtras;
11439 ps.codePath = new File(pkg.applicationInfo.sourceDir);
11440 ps.codePathString = ps.codePath.getPath();
11441 ps.resourcePath = new File(
11442 pkg.applicationInfo.publicSourceDir);
11443 ps.resourcePathString = ps.resourcePath.getPath();
11444 ps.nativeLibraryPathString = newNativePath;
11445 // Set the application info flag
11446 // correctly.
11447 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
11448 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
11449 } else {
11450 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
11451 }
11452 ps.setFlags(pkg.applicationInfo.flags);
11453 mAppDirs.remove(oldCodePath);
11454 mAppDirs.put(newCodePath, pkg);
11455 // Persist settings
11456 mSettings.writeLPr();
11457 }
11458 }
11459 }
11460 }
11461 // Send resources available broadcast
Christopher Tated15967482013-10-04 13:57:22 -070011462 sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null);
Kenny Root447106f2011-03-23 11:00:15 -070011463 }
11464 }
11465 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
11466 // Clean up failed installation
11467 if (mp.targetArgs != null) {
Kenny Root6dceb882012-04-12 14:23:49 -070011468 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
11469 -1);
Kenny Root447106f2011-03-23 11:00:15 -070011470 }
11471 } else {
11472 // Force a gc to clear things up.
11473 Runtime.getRuntime().gc();
11474 // Delete older code
11475 synchronized (mInstallLock) {
11476 mp.srcArgs.doPostDeleteLI(true);
11477 }
11478 }
Kenny Rootdeb11262010-08-02 11:36:21 -070011479
Kenny Root447106f2011-03-23 11:00:15 -070011480 // Allow more operations on this file if we didn't fail because
11481 // an operation was already pending for this package.
11482 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
11483 synchronized (mPackages) {
11484 PackageParser.Package pkg = mPackages.get(mp.packageName);
11485 if (pkg != null) {
11486 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -070011487 }
11488 }
Kenny Root447106f2011-03-23 11:00:15 -070011489 }
Kenny Rootdeb11262010-08-02 11:36:21 -070011490
Kenny Root447106f2011-03-23 11:00:15 -070011491 IPackageMoveObserver observer = mp.observer;
11492 if (observer != null) {
11493 try {
11494 observer.packageMoved(mp.packageName, returnCode);
11495 } catch (RemoteException e) {
11496 Log.i(TAG, "Observer no longer exists.");
11497 }
11498 }
11499 }
11500 });
11501 }
11502
11503 public boolean setInstallLocation(int loc) {
11504 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
11505 null);
11506 if (getInstallLocation() == loc) {
11507 return true;
11508 }
11509 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
11510 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
Jeff Sharkey625239a2012-09-26 22:03:49 -070011511 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
11512 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
Kenny Root447106f2011-03-23 11:00:15 -070011513 return true;
11514 }
11515 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080011516 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -070011517
Kenny Root447106f2011-03-23 11:00:15 -070011518 public int getInstallLocation() {
Jeff Sharkey625239a2012-09-26 22:03:49 -070011519 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
11520 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION,
Kenny Root447106f2011-03-23 11:00:15 -070011521 PackageHelper.APP_INSTALL_AUTO);
11522 }
Amith Yamasani0b285492011-04-14 17:35:23 -070011523
Amith Yamasani258848d2012-08-10 17:06:33 -070011524 /** Called by UserManagerService */
Dianne Hackborn4428e172012-08-24 17:43:05 -070011525 void cleanUpUserLILPw(int userHandle) {
Christopher Tate1e08f5c2013-05-02 13:27:27 -070011526 mDirtyUsers.remove(userHandle);
Dianne Hackborn4428e172012-08-24 17:43:05 -070011527 mSettings.removeUserLPr(userHandle);
Christopher Tate1e08f5c2013-05-02 13:27:27 -070011528 mPendingBroadcasts.remove(userHandle);
Dianne Hackborn4428e172012-08-24 17:43:05 -070011529 if (mInstaller != null) {
11530 // Technically, we shouldn't be doing this with the package lock
11531 // held. However, this is very rare, and there is already so much
11532 // other disk I/O going on, that we'll let it slide for now.
11533 mInstaller.removeUserDataDirs(userHandle);
11534 }
11535 }
11536
11537 /** Called by UserManagerService */
11538 void createNewUserLILPw(int userHandle, File path) {
11539 if (mInstaller != null) {
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080011540 mSettings.createNewUserLILPw(this, mInstaller, userHandle, path);
Amith Yamasani13593602012-03-22 16:16:17 -070011541 }
11542 }
11543
Kenny Root0aaa0d92011-09-12 16:42:55 -070011544 @Override
11545 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
11546 mContext.enforceCallingOrSelfPermission(
11547 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
11548 "Only package verification agents can read the verifier device identity");
11549
11550 synchronized (mPackages) {
11551 return mSettings.getVerifierDeviceIdentityLPw();
11552 }
11553 }
Amith Yamasani742a6712011-05-04 14:49:28 -070011554
Amith Yamasani13593602012-03-22 16:16:17 -070011555 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -070011556 public void setPermissionEnforced(String permission, boolean enforced) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011557 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
11558 if (READ_EXTERNAL_STORAGE.equals(permission)) {
11559 synchronized (mPackages) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -070011560 if (mSettings.mReadExternalStorageEnforced == null
11561 || mSettings.mReadExternalStorageEnforced != enforced) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -070011562 mSettings.mReadExternalStorageEnforced = enforced;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011563 mSettings.writeLPr();
Dianne Hackbornf1b78242013-04-08 22:28:59 -070011564 }
11565 }
11566 // kill any non-foreground processes so we restart them and
11567 // grant/revoke the GID.
11568 final IActivityManager am = ActivityManagerNative.getDefault();
11569 if (am != null) {
11570 final long token = Binder.clearCallingIdentity();
11571 try {
11572 am.killProcessesBelowForeground("setPermissionEnforcement");
11573 } catch (RemoteException e) {
11574 } finally {
11575 Binder.restoreCallingIdentity(token);
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011576 }
11577 }
11578 } else {
11579 throw new IllegalArgumentException("No selective enforcement for " + permission);
11580 }
11581 }
11582
11583 @Override
Jeff Sharkey02e4d16e2013-08-12 20:31:36 -070011584 @Deprecated
Jeff Sharkey5d32e772012-04-12 15:59:23 -070011585 public boolean isPermissionEnforced(String permission) {
Jeff Sharkey02e4d16e2013-08-12 20:31:36 -070011586 return true;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070011587 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070011588
Adam Lesinski182f73f2013-12-05 16:48:06 -080011589 @Override
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070011590 public boolean isStorageLow() {
11591 final long token = Binder.clearCallingIdentity();
11592 try {
Adam Lesinski182f73f2013-12-05 16:48:06 -080011593 final DeviceStorageMonitorInternal
11594 dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
11595 if (dsm != null) {
11596 return dsm.isMemoryLow();
11597 } else {
11598 return false;
11599 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070011600 } finally {
11601 Binder.restoreCallingIdentity(token);
11602 }
11603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604}