blob: e17b53eb9e03994025ac57d3b621480aed7d32ca [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 Hackbornfc8b7fe2012-06-18 15:38:12 -070038import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080039import com.android.internal.util.XmlUtils;
Kenny Rootcf0b38c2011-03-22 14:17:59 -070040import com.android.server.DeviceStorageMonitorService;
41import com.android.server.EventLogTags;
42import com.android.server.IntentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
Jason parksa3cdaa52011-01-13 14:15:43 -060044import org.xmlpull.v1.XmlPullParser;
45import org.xmlpull.v1.XmlPullParserException;
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070046import org.xmlpull.v1.XmlSerializer;
Jason parksa3cdaa52011-01-13 14:15:43 -060047
rich canningsa2064df2012-09-30 14:52:41 -070048import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.app.ActivityManagerNative;
50import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080051import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Kenny Root5ab21572011-07-27 11:11:19 -070053import android.content.BroadcastReceiver;
Jason parksa3cdaa52011-01-13 14:15:43 -060054import android.content.ComponentName;
Kenny Root27989422011-02-23 16:28:26 -080055import android.content.Context;
Dianne Hackbornecb0e632010-04-07 20:22:55 -070056import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.Intent;
58import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070059import android.content.IntentSender;
Jason parks1125d782011-01-12 09:47:26 -060060import android.content.ServiceConnection;
Jason parksa3cdaa52011-01-13 14:15:43 -060061import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.pm.ActivityInfo;
63import android.content.pm.ApplicationInfo;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070064import android.content.pm.ContainerEncryptionParams;
Dianne Hackborn49237342009-08-27 20:08:01 -070065import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageDeleteObserver;
68import android.content.pm.IPackageInstallObserver;
69import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080070import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.IPackageStatsObserver;
72import android.content.pm.InstrumentationInfo;
Geremy Condraf1bcca82013-01-07 22:35:24 -080073import android.content.pm.KeySet;
Dianne Hackborn7767eac2012-08-23 18:25:40 -070074import android.content.pm.PackageCleanItem;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080076import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.pm.PackageManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060078import android.content.pm.PackageParser;
Dianne Hackborn7767eac2012-08-23 18:25:40 -070079import android.content.pm.PackageUserState;
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -070080import android.content.pm.PackageParser.ActivityIntentInfo;
Kenny Root27989422011-02-23 16:28:26 -080081import android.content.pm.PackageStats;
Kenny Root0e2c0f32011-04-15 17:50:10 -070082import android.content.pm.ParceledListSlice;
Jason parksa3cdaa52011-01-13 14:15:43 -060083import android.content.pm.PermissionGroupInfo;
Kenny Root27989422011-02-23 16:28:26 -080084import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.content.pm.ProviderInfo;
86import android.content.pm.ResolveInfo;
87import android.content.pm.ServiceInfo;
88import android.content.pm.Signature;
Kenny Root5ab21572011-07-27 11:11:19 -070089import android.content.pm.ManifestDigest;
rich cannings706e8ba2012-08-20 13:20:14 -070090import android.content.pm.VerificationParams;
Kenny Root0aaa0d92011-09-12 16:42:55 -070091import android.content.pm.VerifierDeviceIdentity;
Kenny Root05ca4c92011-09-15 10:36:25 -070092import android.content.pm.VerifierInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.net.Uri;
94import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070095import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.Bundle;
Kenny Root27989422011-02-23 16:28:26 -080097import android.os.Environment;
98import android.os.FileObserver;
99import android.os.FileUtils;
100import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800102import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700103import android.os.Looper;
104import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.os.ParcelFileDescriptor;
107import android.os.Process;
Kenny Root27989422011-02-23 16:28:26 -0800108import android.os.RemoteException;
rpcraig554cb0c2012-07-05 06:41:43 -0400109import android.os.SELinux;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.os.ServiceManager;
111import android.os.SystemClock;
112import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700113import android.os.UserHandle;
Amith Yamasanie4cf7342012-12-17 11:12:09 -0800114import android.os.UserManager;
Jeff Sharkeyb049e212012-09-07 23:16:01 -0700115import android.os.Environment.UserEnvironment;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800116import android.security.SystemKeyStore;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800117import android.util.Base64;
Kenny Root27989422011-02-23 16:28:26 -0800118import android.util.DisplayMetrics;
119import android.util.EventLog;
120import android.util.Log;
121import android.util.LogPrinter;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800122import android.util.LongSparseArray;
Kenny Root27989422011-02-23 16:28:26 -0800123import android.util.Slog;
124import android.util.SparseArray;
125import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import android.view.Display;
127import android.view.WindowManager;
128
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -0700129import java.io.BufferedOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130import java.io.File;
131import java.io.FileDescriptor;
132import java.io.FileInputStream;
133import java.io.FileNotFoundException;
134import java.io.FileOutputStream;
135import java.io.FileReader;
136import java.io.FilenameFilter;
137import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800139import java.security.NoSuchAlgorithmException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700140import java.security.PublicKey;
141import java.security.cert.CertificateException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800142import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143import java.util.ArrayList;
144import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700145import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146import java.util.Collections;
147import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800148import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149import java.util.HashMap;
150import java.util.HashSet;
151import java.util.Iterator;
152import java.util.List;
153import java.util.Map;
154import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155
Kenny Root66269ea2011-07-12 14:14:01 -0700156import libcore.io.ErrnoException;
Kenny Root3f99afc2012-04-14 10:13:10 -0700157import libcore.io.IoUtils;
Kenny Root66269ea2011-07-12 14:14:01 -0700158import libcore.io.Libcore;
Kenny Root786cbca2012-08-16 11:10:58 -0700159import libcore.io.StructStat;
Kenny Root66269ea2011-07-12 14:14:01 -0700160
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700161/**
162 * Keep track of all those .apks everywhere.
163 *
164 * This is very central to the platform's security; please run the unit
165 * tests whenever making modifications here:
166 *
167mmm frameworks/base/tests/AndroidTests
168adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
169adb 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 -0700170 *
171 * {@hide}
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700172 */
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700173public class PackageManagerService extends IPackageManager.Stub {
174 static final String TAG = "PackageManager";
175 static final boolean DEBUG_SETTINGS = false;
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -0800176 static final boolean DEBUG_PREFERRED = true;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700177 static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800178 private static final boolean DEBUG_INSTALL = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800179 private static final boolean DEBUG_REMOVE = false;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700180 private static final boolean DEBUG_BROADCASTS = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800181 private static final boolean DEBUG_SHOW_INFO = false;
182 private static final boolean DEBUG_PACKAGE_INFO = false;
183 private static final boolean DEBUG_INTENT_MATCHING = false;
184 private static final boolean DEBUG_PACKAGE_SCANNING = false;
185 private static final boolean DEBUG_APP_DIR_OBSERVER = false;
Kenny Root05ca4c92011-09-15 10:36:25 -0700186 private static final boolean DEBUG_VERIFY = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400189 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700190 private static final int NFC_UID = Process.NFC_UID;
Jaikumar Ganesh1abb1cb2012-01-25 16:14:50 -0800191 private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
Dianne Hackborn514074f2013-02-11 10:52:46 -0800192 private static final int SHELL_UID = Process.SHELL_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 private static final boolean GET_CERTIFICATES = true;
195
196 private static final int REMOVE_EVENTS =
197 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
198 private static final int ADD_EVENTS =
199 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
200
201 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800202 // Suffix used during package installation when copying/moving
203 // package apks to install directory.
204 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
206 static final int SCAN_MONITOR = 1<<0;
207 static final int SCAN_NO_DEX = 1<<1;
208 static final int SCAN_FORCE_DEX = 1<<2;
209 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800210 static final int SCAN_NEW_INSTALL = 1<<4;
211 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700212 static final int SCAN_UPDATE_TIME = 1<<6;
Dianne Hackborn661cd522011-08-22 00:26:20 -0700213 static final int SCAN_DEFER_DEX = 1<<7;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -0700214 static final int SCAN_BOOTING = 1<<8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700216 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700217
Kenny Root5ab21572011-07-27 11:11:19 -0700218 /**
219 * Whether verification is enabled by default.
220 */
rich cannings36c67c22012-09-16 16:20:23 -0700221 private static final boolean DEFAULT_VERIFY_ENABLE = true;
Kenny Root5ab21572011-07-27 11:11:19 -0700222
223 /**
224 * The default maximum time to wait for the verification agent to return in
225 * milliseconds.
226 */
rich canningsaa8513e2012-05-21 16:15:23 -0700227 private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
Kenny Root5ab21572011-07-27 11:11:19 -0700228
rich canningsa6cfe522012-05-21 15:50:56 -0700229 /**
230 * The default response for package verification timeout.
231 *
232 * This can be either PackageManager.VERIFICATION_ALLOW or
233 * PackageManager.VERIFICATION_REJECT.
234 */
235 private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
236
Kenny Root11128572010-10-11 10:51:32 -0700237 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
238
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800239 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700240 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800241 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700242
Kenny Root05ca4c92011-09-15 10:36:25 -0700243 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
244
Kenny Root85387d72010-08-26 10:13:11 -0700245 private static final String LIB_DIR_NAME = "lib";
246
Kenny Rootc78a8072010-07-27 15:18:38 -0700247 static final String mTempContainerPrefix = "smdl2tmp";
248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
250 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700251 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
Dianne Hackborn851a5412009-05-08 12:06:44 -0700253 final int mSdkVersion = Build.VERSION.SDK_INT;
254 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
255 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 final Context mContext;
258 final boolean mFactoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700259 final boolean mOnlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700260 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 final DisplayMetrics mMetrics;
262 final int mDefParseFlags;
263 final String[] mSeparateProcesses;
264
265 // This is where all application persistent data goes.
266 final File mAppDataDir;
267
Amith Yamasani0b285492011-04-14 17:35:23 -0700268 // This is where all application persistent data goes for secondary users.
269 final File mUserAppDataDir;
270
Kenny Root51a573c2012-05-17 13:30:28 -0700271 /** The location for ASEC container files on internal storage. */
272 final String mAsecInternalPath;
273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 // This is the object monitoring the framework dir.
275 final FileObserver mFrameworkInstallObserver;
276
277 // This is the object monitoring the system app dir.
278 final FileObserver mSystemInstallObserver;
279
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700280 // This is the object monitoring the system app dir.
281 final FileObserver mVendorInstallObserver;
282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 // This is the object monitoring mAppInstallDir.
284 final FileObserver mAppInstallObserver;
285
286 // This is the object monitoring mDrmAppPrivateInstallDir.
287 final FileObserver mDrmAppInstallObserver;
288
Kenny Rootddbe50d2012-09-06 13:18:37 -0700289 // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 // LOCK HELD. Can be called with mInstallLock held.
291 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 final File mFrameworkDir;
294 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700295 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700297 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298
Kenny Rootddbe50d2012-09-06 13:18:37 -0700299 /**
300 * Directory to which applications installed internally have native
301 * libraries copied.
302 */
303 private File mAppLibInstallDir;
304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
306 // apps.
307 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 // Lock for state used when installing and doing other long running
312 // operations. Methods that must be called with this lock held have
313 // the prefix "LI".
314 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 // These are the directories in the 3rd party applications installed dir
317 // that we have currently loaded packages from. Keys are the application's
318 // installed zip file (absolute codePath), and values are Package.
319 final HashMap<String, PackageParser.Package> mAppDirs =
320 new HashMap<String, PackageParser.Package>();
321
322 // Information for the parser to write more useful error messages.
323 File mScanningPath;
324 int mLastScanError;
325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 // Keys are String (package name), values are Package. This also serves
329 // as the lock for the global state. Methods that must be called with
330 // this lock held have the prefix "LP".
331 final HashMap<String, PackageParser.Package> mPackages =
332 new HashMap<String, PackageParser.Package>();
333
334 final Settings mSettings;
335 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336
337 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
338 int[] mGlobalGids;
339
340 // These are the built-in uid -> permission mappings that were read from the
341 // etc/permissions.xml file.
342 final SparseArray<HashSet<String>> mSystemPermissions =
343 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 // These are the built-in shared libraries that were read from the
346 // etc/permissions.xml file.
347 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800348
Dianne Hackborn49237342009-08-27 20:08:01 -0700349 // Temporary for building the final shared libraries for an .apk.
350 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800351
Dianne Hackborn49237342009-08-27 20:08:01 -0700352 // These are the features this devices supports that were read from the
353 // etc/permissions.xml file.
354 final HashMap<String, FeatureInfo> mAvailableFeatures =
355 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 // All available activities, for your resolving pleasure.
358 final ActivityIntentResolver mActivities =
359 new ActivityIntentResolver();
360
361 // All available receivers, for your resolving pleasure.
362 final ActivityIntentResolver mReceivers =
363 new ActivityIntentResolver();
364
365 // All available services, for your resolving pleasure.
366 final ServiceIntentResolver mServices = new ServiceIntentResolver();
367
368 // Keys are String (provider class name), values are Provider.
369 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
370 new HashMap<ComponentName, PackageParser.Provider>();
371
372 // Mapping from provider base names (first directory in content URI codePath)
373 // to the provider information.
374 final HashMap<String, PackageParser.Provider> mProviders =
375 new HashMap<String, PackageParser.Provider>();
376
377 // Mapping from instrumentation class names to info about them.
378 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
379 new HashMap<ComponentName, PackageParser.Instrumentation>();
380
381 // Mapping from permission names to info about them.
382 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
383 new HashMap<String, PackageParser.PermissionGroup>();
384
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800385 // Packages whose data we have transfered into another package, thus
386 // should no longer exist.
387 final HashSet<String> mTransferedPackages = new HashSet<String>();
388
Dianne Hackborn854060af2009-07-09 18:14:31 -0700389 // Broadcast actions that are only available to the system.
390 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800391
Kenny Root5ab21572011-07-27 11:11:19 -0700392 /** List of packages waiting for verification. */
Kenny Root05ca4c92011-09-15 10:36:25 -0700393 final SparseArray<PackageVerificationState> mPendingVerification
394 = new SparseArray<PackageVerificationState>();
Kenny Root5ab21572011-07-27 11:11:19 -0700395
Dianne Hackborn661cd522011-08-22 00:26:20 -0700396 final ArrayList<PackageParser.Package> mDeferredDexOpt =
397 new ArrayList<PackageParser.Package>();
398
Kenny Root5ab21572011-07-27 11:11:19 -0700399 /** Token for keys in mPendingVerification. */
400 private int mPendingVerificationToken = 0;
401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 boolean mSystemReady;
403 boolean mSafeMode;
404 boolean mHasSystemUidErrors;
405
406 ApplicationInfo mAndroidApplication;
407 final ActivityInfo mResolveActivity = new ActivityInfo();
408 final ResolveInfo mResolveInfo = new ResolveInfo();
409 ComponentName mResolveComponentName;
410 PackageParser.Package mPlatformPackage;
411
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700412 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800413 final HashMap<String, ArrayList<String>> mPendingBroadcasts
414 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800415 // Service Connection to remote media container service to copy
416 // package uri's from external media onto secure containers
417 // or internal storage.
418 private IMediaContainerService mContainerService = null;
419
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700420 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800421 static final int MCS_BOUND = 3;
422 static final int END_COPY = 4;
423 static final int INIT_COPY = 5;
424 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800425 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800426 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800427 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800428 static final int MCS_RECONNECT = 10;
429 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700430 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700431 static final int WRITE_SETTINGS = 13;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700432 static final int WRITE_PACKAGE_RESTRICTIONS = 14;
Kenny Root5ab21572011-07-27 11:11:19 -0700433 static final int PACKAGE_VERIFIED = 15;
434 static final int CHECK_PENDING_VERIFICATION = 16;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700435
436 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800437
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700438 // Delay time in millisecs
439 static final int BROADCAST_DELAY = 10 * 1000;
Kenny Root9718cf52011-02-23 16:45:26 -0800440
Amith Yamasani258848d2012-08-10 17:06:33 -0700441 static UserManagerService sUserManager;
Amith Yamasani0b285492011-04-14 17:35:23 -0700442
Amith Yamasani483f3b02012-03-13 16:08:00 -0700443 // Stores a list of users whose package restrictions file needs to be updated
444 private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
445
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800446 final private DefaultContainerConnection mDefContainerConn =
447 new DefaultContainerConnection();
448 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800449 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800450 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800451 IMediaContainerService imcs =
452 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800453 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800454 }
455
456 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800457 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800458 }
459 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700460
Christopher Tate1bb69062010-02-19 17:02:12 -0800461 // Recordkeeping of restore-after-install operations that are currently in flight
462 // between the Package Manager and the Backup Manager
463 class PostInstallData {
464 public InstallArgs args;
465 public PackageInstalledInfo res;
466
467 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
468 args = _a;
469 res = _r;
470 }
471 };
472 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
473 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
474
Kenny Root05ca4c92011-09-15 10:36:25 -0700475 private final String mRequiredVerifierPackage;
476
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700477 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800478 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800479 final ArrayList<HandlerParams> mPendingInstalls =
480 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800481
482 private boolean connectToService() {
483 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
484 " DefaultContainerService");
485 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700486 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Amith Yamasani27b89e62013-01-16 12:30:11 -0800487 if (mContext.bindServiceAsUser(service, mDefContainerConn,
488 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700489 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800490 mBound = true;
491 return true;
492 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700493 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800494 return false;
495 }
496
497 private void disconnectService() {
498 mContainerService = null;
499 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700500 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800501 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700502 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800503 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800504
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700505 PackageHandler(Looper looper) {
506 super(looper);
507 }
Dianne Hackborn7d608422011-08-07 16:24:18 -0700508
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700509 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700510 try {
511 doHandleMessage(msg);
512 } finally {
513 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
514 }
515 }
516
517 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700518 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800519 case INIT_COPY: {
Kenny Root5ab21572011-07-27 11:11:19 -0700520 if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800521 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800522 int idx = mPendingInstalls.size();
Kenny Root5ab21572011-07-27 11:11:19 -0700523 if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800524 // If a bind was already initiated we dont really
525 // need to do anything. The pending install
526 // will be processed later on.
527 if (!mBound) {
528 // If this is the only one pending we might
529 // have to bind to the service again.
530 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800531 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800532 params.serviceError();
533 return;
534 } else {
535 // Once we bind to the service, the first
536 // pending request will be processed.
537 mPendingInstalls.add(idx, params);
538 }
539 } else {
540 mPendingInstalls.add(idx, params);
541 // Already bound to the service. Just make
542 // sure we trigger off processing the first request.
543 if (idx == 0) {
544 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800545 }
546 }
547 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800548 }
549 case MCS_BOUND: {
Kenny Root5ab21572011-07-27 11:11:19 -0700550 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800551 if (msg.obj != null) {
552 mContainerService = (IMediaContainerService) msg.obj;
553 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800554 if (mContainerService == null) {
555 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800556 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800557 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800558 // Indicate service bind error
559 params.serviceError();
560 }
561 mPendingInstalls.clear();
562 } else if (mPendingInstalls.size() > 0) {
563 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800564 if (params != null) {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700565 if (params.startCopy()) {
566 // We are done... look for more work or to
567 // go idle.
568 if (DEBUG_SD_INSTALL) Log.i(TAG,
569 "Checking for more work or unbind...");
570 // Delete pending install
571 if (mPendingInstalls.size() > 0) {
572 mPendingInstalls.remove(0);
573 }
574 if (mPendingInstalls.size() == 0) {
575 if (mBound) {
576 if (DEBUG_SD_INSTALL) Log.i(TAG,
577 "Posting delayed MCS_UNBIND");
578 removeMessages(MCS_UNBIND);
579 Message ubmsg = obtainMessage(MCS_UNBIND);
580 // Unbind after a little delay, to avoid
581 // continual thrashing.
582 sendMessageDelayed(ubmsg, 10000);
583 }
584 } else {
585 // There are more pending requests in queue.
586 // Just post MCS_BOUND message to trigger processing
587 // of next pending install.
588 if (DEBUG_SD_INSTALL) Log.i(TAG,
589 "Posting MCS_BOUND for next woek");
590 mHandler.sendEmptyMessage(MCS_BOUND);
591 }
592 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800593 }
594 } else {
595 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800596 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800597 }
598 break;
599 }
Kenny Root5ab21572011-07-27 11:11:19 -0700600 case MCS_RECONNECT: {
601 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800602 if (mPendingInstalls.size() > 0) {
603 if (mBound) {
604 disconnectService();
605 }
606 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800607 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800608 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800609 // Indicate service bind error
610 params.serviceError();
611 }
612 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800613 }
614 }
615 break;
616 }
Kenny Root5ab21572011-07-27 11:11:19 -0700617 case MCS_UNBIND: {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700618 // If there is no actual work left, then time to unbind.
Kenny Root5ab21572011-07-27 11:11:19 -0700619 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
620
621 if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800622 if (mBound) {
Kenny Root5ab21572011-07-27 11:11:19 -0700623 if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
624
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800625 disconnectService();
626 }
Kenny Root5ab21572011-07-27 11:11:19 -0700627 } else if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800628 // There are more pending requests in queue.
629 // Just post MCS_BOUND message to trigger processing
630 // of next pending install.
631 mHandler.sendEmptyMessage(MCS_BOUND);
632 }
Kenny Root5ab21572011-07-27 11:11:19 -0700633
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800634 break;
635 }
636 case MCS_GIVE_UP: {
Kenny Root5ab21572011-07-27 11:11:19 -0700637 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
Kenny Root60f7ad82011-03-22 12:49:06 -0700638 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800639 break;
640 }
Kenny Root5ab21572011-07-27 11:11:19 -0700641 case SEND_PENDING_BROADCAST: {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800642 String packages[];
Kenny Root60f7ad82011-03-22 12:49:06 -0700643 ArrayList<String> components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700644 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700645 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700646 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700647 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800648 if (mPendingBroadcasts == null) {
649 return;
650 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700651 size = mPendingBroadcasts.size();
652 if (size <= 0) {
653 // Nothing to be done. Just return
654 return;
655 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800656 packages = new String[size];
657 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700658 uids = new int[size];
Andy McFadden2f362292012-01-20 14:43:38 -0800659 Iterator<Map.Entry<String, ArrayList<String>>>
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800660 it = mPendingBroadcasts.entrySet().iterator();
661 int i = 0;
662 while (it.hasNext() && i < size) {
Andy McFadden2f362292012-01-20 14:43:38 -0800663 Map.Entry<String, ArrayList<String>> ent = it.next();
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800664 packages[i] = ent.getKey();
665 components[i] = ent.getValue();
666 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -0700667 uids[i] = (ps != null) ? ps.appId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800668 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700669 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800670 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700671 mPendingBroadcasts.clear();
672 }
673 // Send broadcasts
674 for (int i = 0; i < size; i++) {
Kenny Root60f7ad82011-03-22 12:49:06 -0700675 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700676 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700677 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700678 break;
679 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800680 case START_CLEANING_PACKAGE: {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700681 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Jeff Sharkey752cd922012-09-23 16:25:12 -0700682 final String packageName = (String)msg.obj;
683 final int userId = msg.arg1;
684 final boolean andCode = msg.arg2 != 0;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800685 synchronized (mPackages) {
Jeff Sharkey752cd922012-09-23 16:25:12 -0700686 if (userId == UserHandle.USER_ALL) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700687 int[] users = sUserManager.getUserIds();
688 for (int user : users) {
Jeff Sharkey752cd922012-09-23 16:25:12 -0700689 mSettings.addPackageToCleanLPw(
690 new PackageCleanItem(user, packageName, andCode));
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700691 }
692 } else {
Jeff Sharkey752cd922012-09-23 16:25:12 -0700693 mSettings.addPackageToCleanLPw(
694 new PackageCleanItem(userId, packageName, andCode));
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800695 }
696 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700697 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Jeff Sharkey752cd922012-09-23 16:25:12 -0700698 startCleaningPackages();
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800699 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800700 case POST_INSTALL: {
701 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
702 PostInstallData data = mRunningInstalls.get(msg.arg1);
703 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700704 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800705
706 if (data != null) {
707 InstallArgs args = data.args;
708 PackageInstalledInfo res = data.res;
709
710 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700711 res.removedInfo.sendBroadcast(false, true, false);
Christopher Tate1bb69062010-02-19 17:02:12 -0800712 Bundle extras = new Bundle(1);
713 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackborn786b4402012-08-27 15:14:02 -0700714 // Determine the set of users who are adding this
715 // package for the first time vs. those who are seeing
716 // an update.
717 int[] firstUsers;
718 int[] updateUsers = new int[0];
719 if (res.origUsers == null || res.origUsers.length == 0) {
720 firstUsers = res.newUsers;
721 } else {
722 firstUsers = new int[0];
723 for (int i=0; i<res.newUsers.length; i++) {
724 int user = res.newUsers[i];
725 boolean isNew = true;
726 for (int j=0; j<res.origUsers.length; j++) {
727 if (res.origUsers[j] == user) {
728 isNew = false;
729 break;
730 }
731 }
732 if (isNew) {
733 int[] newFirst = new int[firstUsers.length+1];
734 System.arraycopy(firstUsers, 0, newFirst, 0,
735 firstUsers.length);
736 newFirst[firstUsers.length] = user;
737 firstUsers = newFirst;
738 } else {
739 int[] newUpdate = new int[updateUsers.length+1];
740 System.arraycopy(updateUsers, 0, newUpdate, 0,
741 updateUsers.length);
742 newUpdate[updateUsers.length] = user;
743 updateUsers = newUpdate;
744 }
745 }
746 }
747 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
748 res.pkg.applicationInfo.packageName,
749 extras, null, null, firstUsers);
Christopher Tate1bb69062010-02-19 17:02:12 -0800750 final boolean update = res.removedInfo.removedPackage != null;
751 if (update) {
752 extras.putBoolean(Intent.EXTRA_REPLACING, true);
753 }
754 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
755 res.pkg.applicationInfo.packageName,
Dianne Hackborn786b4402012-08-27 15:14:02 -0700756 extras, null, null, updateUsers);
Christopher Tate1bb69062010-02-19 17:02:12 -0800757 if (update) {
758 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
759 res.pkg.applicationInfo.packageName,
Dianne Hackborn786b4402012-08-27 15:14:02 -0700760 extras, null, null, updateUsers);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800761 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
762 null, null,
Dianne Hackborn786b4402012-08-27 15:14:02 -0700763 res.pkg.applicationInfo.packageName, null, updateUsers);
Christopher Tate1bb69062010-02-19 17:02:12 -0800764 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700765 if (res.removedInfo.args != null) {
766 // Remove the replaced package's older resources safely now
767 deleteOld = true;
768 }
Matt Finifterf8a98ed2012-05-14 15:43:34 -0700769
770 // Log current value of "unknown sources" setting
771 EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
772 getUnknownSourcesSettings());
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700773 }
774 // Force a gc to clear up things
775 Runtime.getRuntime().gc();
776 // We delete after a gc for applications on sdcard.
777 if (deleteOld) {
778 synchronized (mInstallLock) {
779 res.removedInfo.args.doPostDeleteLI(true);
780 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800781 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800782 if (args.observer != null) {
783 try {
784 args.observer.packageInstalled(res.name, res.returnCode);
785 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800786 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800787 }
788 }
789 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800790 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800791 }
792 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700793 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700794 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
795 boolean reportStatus = msg.arg1 == 1;
796 boolean doGc = msg.arg2 == 1;
797 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
798 if (doGc) {
799 // Force a gc to clear up stale containers.
800 Runtime.getRuntime().gc();
801 }
802 if (msg.obj != null) {
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700803 @SuppressWarnings("unchecked")
Kenny Root6dceb882012-04-12 14:23:49 -0700804 Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700805 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
806 // Unload containers
807 unloadAllContainers(args);
808 }
809 if (reportStatus) {
810 try {
811 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
812 PackageHelper.getMountService().finishMediaUpdate();
813 } catch (RemoteException e) {
814 Log.e(TAG, "MountService not running?");
815 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700816 }
817 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700818 case WRITE_SETTINGS: {
819 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
820 synchronized (mPackages) {
821 removeMessages(WRITE_SETTINGS);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700822 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
Kenny Root447106f2011-03-23 11:00:15 -0700823 mSettings.writeLPr();
Amith Yamasani483f3b02012-03-13 16:08:00 -0700824 mDirtyUsers.clear();
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700825 }
826 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
827 } break;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700828 case WRITE_PACKAGE_RESTRICTIONS: {
Dianne Hackborne7f97212011-02-24 14:40:20 -0800829 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
830 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -0700831 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
832 for (int userId : mDirtyUsers) {
833 mSettings.writePackageRestrictionsLPr(userId);
834 }
835 mDirtyUsers.clear();
Dianne Hackborne7f97212011-02-24 14:40:20 -0800836 }
837 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
838 } break;
Kenny Root5ab21572011-07-27 11:11:19 -0700839 case CHECK_PENDING_VERIFICATION: {
840 final int verificationId = msg.arg1;
Kenny Root05ca4c92011-09-15 10:36:25 -0700841 final PackageVerificationState state = mPendingVerification.get(verificationId);
Kenny Root5ab21572011-07-27 11:11:19 -0700842
rich canningsd9ef3e52012-08-22 14:28:05 -0700843 if ((state != null) && !state.timeoutExtended()) {
Kenny Root05ca4c92011-09-15 10:36:25 -0700844 final InstallArgs args = state.getInstallArgs();
Kenny Roota503a0f2011-10-03 14:45:28 -0700845 Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
Kenny Root5ab21572011-07-27 11:11:19 -0700846 mPendingVerification.remove(verificationId);
847
rich canningsa6cfe522012-05-21 15:50:56 -0700848 int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
849
850 if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
rich canningsd9ef3e52012-08-22 14:28:05 -0700851 Slog.i(TAG, "Continuing with installation of "
852 + args.packageURI.toString());
853 state.setVerifierResponse(Binder.getCallingUid(),
854 PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
rich canningsd1b5cfc2012-08-29 14:49:51 -0700855 broadcastPackageVerified(verificationId, args.packageURI,
rich canningsd55deb02012-10-02 14:53:08 -0700856 PackageManager.VERIFICATION_ALLOW,
857 state.getInstallArgs().getUser());
rich canningsd9ef3e52012-08-22 14:28:05 -0700858 try {
859 ret = args.copyApk(mContainerService, true);
860 } catch (RemoteException e) {
861 Slog.e(TAG, "Could not contact the ContainerService");
862 }
rich canningsd1b5cfc2012-08-29 14:49:51 -0700863 } else {
864 broadcastPackageVerified(verificationId, args.packageURI,
rich canningsd55deb02012-10-02 14:53:08 -0700865 PackageManager.VERIFICATION_REJECT,
866 state.getInstallArgs().getUser());
rich canningsa6cfe522012-05-21 15:50:56 -0700867 }
868
Kenny Root5ab21572011-07-27 11:11:19 -0700869 processPendingInstall(args, ret);
Kenny Root5ab21572011-07-27 11:11:19 -0700870 mHandler.sendEmptyMessage(MCS_UNBIND);
871 }
Kenny Root5ab21572011-07-27 11:11:19 -0700872 break;
873 }
874 case PACKAGE_VERIFIED: {
875 final int verificationId = msg.arg1;
Kenny Root5ab21572011-07-27 11:11:19 -0700876
Kenny Root05ca4c92011-09-15 10:36:25 -0700877 final PackageVerificationState state = mPendingVerification.get(verificationId);
878 if (state == null) {
Kenny Roota503a0f2011-10-03 14:45:28 -0700879 Slog.w(TAG, "Invalid verification token " + verificationId + " received");
Kenny Root5ab21572011-07-27 11:11:19 -0700880 break;
881 }
882
Kenny Root05ca4c92011-09-15 10:36:25 -0700883 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
Kenny Root5ab21572011-07-27 11:11:19 -0700884
Kenny Root05ca4c92011-09-15 10:36:25 -0700885 state.setVerifierResponse(response.callerUid, response.code);
886
887 if (state.isVerificationComplete()) {
888 mPendingVerification.remove(verificationId);
889
890 final InstallArgs args = state.getInstallArgs();
891
892 int ret;
893 if (state.isInstallAllowed()) {
894 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
rich canningsd1b5cfc2012-08-29 14:49:51 -0700895 broadcastPackageVerified(verificationId, args.packageURI,
rich canningsd55deb02012-10-02 14:53:08 -0700896 response.code, state.getInstallArgs().getUser());
Kenny Root05ca4c92011-09-15 10:36:25 -0700897 try {
898 ret = args.copyApk(mContainerService, true);
899 } catch (RemoteException e) {
900 Slog.e(TAG, "Could not contact the ContainerService");
901 }
902 } else {
903 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
Kenny Root5ab21572011-07-27 11:11:19 -0700904 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700905
906 processPendingInstall(args, ret);
907
908 mHandler.sendEmptyMessage(MCS_UNBIND);
Kenny Root5ab21572011-07-27 11:11:19 -0700909 }
910
Kenny Root5ab21572011-07-27 11:11:19 -0700911 break;
912 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700913 }
914 }
915 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800916
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700917 void scheduleWriteSettingsLocked() {
918 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
919 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
920 }
921 }
Amith Yamasani483f3b02012-03-13 16:08:00 -0700922
923 void scheduleWritePackageRestrictionsLocked(int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -0700924 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700925 mDirtyUsers.add(userId);
926 if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
927 mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800928 }
929 }
930
Jeff Brownf69c8122012-09-12 17:00:34 -0700931 public static final IPackageManager main(Context context, Installer installer,
932 boolean factoryTest, boolean onlyCore) {
933 PackageManagerService m = new PackageManagerService(context, installer,
934 factoryTest, onlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 ServiceManager.addService("package", m);
936 return m;
937 }
938
939 static String[] splitString(String str, char sep) {
940 int count = 1;
941 int i = 0;
942 while ((i=str.indexOf(sep, i)) >= 0) {
943 count++;
944 i++;
945 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 String[] res = new String[count];
948 i=0;
949 count = 0;
950 int lastI=0;
951 while ((i=str.indexOf(sep, i)) >= 0) {
952 res[count] = str.substring(lastI, i);
953 count++;
954 i++;
955 lastI = i;
956 }
957 res[count] = str.substring(lastI, str.length());
958 return res;
959 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800960
Jeff Brownf69c8122012-09-12 17:00:34 -0700961 public PackageManagerService(Context context, Installer installer,
962 boolean factoryTest, boolean onlyCore) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800963 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800967 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 mContext = context;
971 mFactoryTest = factoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700972 mOnlyCore = onlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700973 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 mMetrics = new DisplayMetrics();
Amith Yamasani258848d2012-08-10 17:06:33 -0700975 mSettings = new Settings(context);
Kenny Root447106f2011-03-23 11:00:15 -0700976 mSettings.addSharedUserLPw("android.uid.system",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
Dianne Hackborn21fbd1f2012-02-10 10:38:10 -0800978 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
979 mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
980 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
Jaikumar Ganesh1abb1cb2012-01-25 16:14:50 -0800981 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
Dianne Hackborn514074f2013-02-11 10:52:46 -0800982 mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID, ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983
984 String separateProcesses = SystemProperties.get("debug.separate_processes");
985 if (separateProcesses != null && separateProcesses.length() > 0) {
986 if ("*".equals(separateProcesses)) {
987 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
988 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800989 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 } else {
991 mDefParseFlags = 0;
992 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800993 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 + separateProcesses);
995 }
996 } else {
997 mDefParseFlags = 0;
998 mSeparateProcesses = null;
999 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001000
Jeff Brownf69c8122012-09-12 17:00:34 -07001001 mInstaller = installer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002
1003 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
1004 Display d = wm.getDefaultDisplay();
1005 d.getMetrics(mMetrics);
1006
1007 synchronized (mInstallLock) {
Kenny Root447106f2011-03-23 11:00:15 -07001008 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 synchronized (mPackages) {
1010 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07001011 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 File dataDir = Environment.getDataDirectory();
1014 mAppDataDir = new File(dataDir, "data");
Kenny Root584c4cd2012-10-29 10:46:42 -07001015 mAppInstallDir = new File(dataDir, "app");
1016 mAppLibInstallDir = new File(dataDir, "app-lib");
Kenny Root51a573c2012-05-17 13:30:28 -07001017 mAsecInternalPath = new File(dataDir, "app-asec").getPath();
Amith Yamasani0b285492011-04-14 17:35:23 -07001018 mUserAppDataDir = new File(dataDir, "user");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
1020
Dianne Hackborn4428e172012-08-24 17:43:05 -07001021 sUserManager = new UserManagerService(context, this,
1022 mInstallLock, mPackages);
Amith Yamasani0b285492011-04-14 17:35:23 -07001023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 readPermissions();
1025
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08001026 mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false),
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001027 mSdkVersion, mOnlyCore);
Geremy Condraf1bcca82013-01-07 22:35:24 -08001028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001030
1031 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001033
Suchi Amalapurapudaec1722010-01-14 21:25:16 -08001034 // Set flag to monitor and not change apk file paths when
1035 // scanning install directories.
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07001036 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001037 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001038 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001039 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001040 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001045 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001046
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001047 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001048
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001049 /**
1050 * Out of paranoia, ensure that everything in the boot class
1051 * path has been dexed.
1052 */
1053 String bootClassPath = System.getProperty("java.boot.class.path");
1054 if (bootClassPath != null) {
1055 String[] paths = splitString(bootClassPath, ':');
1056 for (int i=0; i<paths.length; i++) {
1057 try {
1058 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
1059 libFiles.add(paths[i]);
1060 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
1061 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001063 } catch (FileNotFoundException e) {
1064 Slog.w(TAG, "Boot class path not found: " + paths[i]);
1065 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -07001066 Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
1067 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 }
1069 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001070 } else {
1071 Slog.w(TAG, "No BOOTCLASSPATH found!");
1072 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001073
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001074 /**
1075 * Also ensure all external libraries have had dexopt run on them.
1076 */
1077 if (mSharedLibraries.size() > 0) {
1078 Iterator<String> libs = mSharedLibraries.values().iterator();
1079 while (libs.hasNext()) {
1080 String lib = libs.next();
1081 try {
1082 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
1083 libFiles.add(lib);
1084 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
1085 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001087 } catch (FileNotFoundException e) {
1088 Slog.w(TAG, "Library not found: " + lib);
1089 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -07001090 Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
1091 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 }
1093 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001094 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001095
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001096 // Gross hack for now: we know this file doesn't contain any
1097 // code, so don't dexopt it to avoid the resulting log spew.
1098 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
1099
1100 /**
1101 * And there are a number of commands implemented in Java, which
1102 * we currently need to do the dexopt on so that they can be
1103 * run from a non-root shell.
1104 */
1105 String[] frameworkFiles = mFrameworkDir.list();
1106 if (frameworkFiles != null) {
1107 for (int i=0; i<frameworkFiles.length; i++) {
1108 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
1109 String path = libPath.getPath();
1110 // Skip the file if we alrady did it.
1111 if (libFiles.contains(path)) {
1112 continue;
1113 }
1114 // Skip the file if it is not a type we want to dexopt.
1115 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
1116 continue;
1117 }
1118 try {
1119 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
1120 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
1121 didDexOpt = true;
1122 }
1123 } catch (FileNotFoundException e) {
1124 Slog.w(TAG, "Jar not found: " + path);
1125 } catch (IOException e) {
1126 Slog.w(TAG, "Exception reading jar: " + path, e);
1127 }
1128 }
1129 }
1130
1131 if (didDexOpt) {
1132 // If we had to do a dexopt of one of the previous
1133 // things, then something on the system has changed.
1134 // Consider this significant, and wipe away all other
1135 // existing dexopt files to ensure we don't leave any
1136 // dangling around.
1137 String[] files = mDalvikCacheDir.list();
1138 if (files != null) {
1139 for (int i=0; i<files.length; i++) {
1140 String fn = files[i];
1141 if (fn.startsWith("data@app@")
1142 || fn.startsWith("data@app-private@")) {
1143 Slog.i(TAG, "Pruning dalvik file: " + fn);
1144 (new File(mDalvikCacheDir, fn)).delete();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001145 }
1146 }
1147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001149
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001150 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 mFrameworkInstallObserver = new AppDirObserver(
1152 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
1153 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001154 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
1155 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001156 scanMode | SCAN_NO_DEX, 0);
Kenny Root51a573c2012-05-17 13:30:28 -07001157
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001158 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
1160 mSystemInstallObserver = new AppDirObserver(
1161 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
1162 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001163 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001164 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Kenny Root208d3412012-05-07 19:42:35 -07001165
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001166 // Collect all vendor packages.
1167 mVendorAppDir = new File("/vendor/app");
1168 mVendorInstallObserver = new AppDirObserver(
1169 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
1170 mVendorInstallObserver.startWatching();
1171 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001172 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001173
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001174 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1175 mInstaller.moveFiles();
1176
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001177 // Prune any system packages that no longer exist.
Kenny Root87b5d7b2012-05-16 13:36:18 -07001178 final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001179 if (!mOnlyCore) {
1180 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1181 while (psit.hasNext()) {
1182 PackageSetting ps = psit.next();
Kenny Root208d3412012-05-07 19:42:35 -07001183
1184 /*
1185 * If this is not a system app, it can't be a
1186 * disable system app.
1187 */
1188 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1189 continue;
1190 }
1191
1192 /*
1193 * If the package is scanned, it's not erased.
1194 */
Kenny Rooteca64b32012-06-25 16:37:32 -07001195 final PackageParser.Package scannedPkg = mPackages.get(ps.name);
1196 if (scannedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07001197 /*
1198 * If the system app is both scanned and in the
1199 * disabled packages list, then it must have been
1200 * added via OTA. Remove it from the currently
1201 * scanned package so the previously user-installed
1202 * application can be scanned.
1203 */
1204 if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
Kenny Rooteca64b32012-06-25 16:37:32 -07001205 Slog.i(TAG, "Expecting better updatd system app for " + ps.name
1206 + "; removing system app");
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001207 removePackageLI(ps, true);
Kenny Root208d3412012-05-07 19:42:35 -07001208 }
1209
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001210 continue;
1211 }
1212
1213 if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001214 psit.remove();
1215 String msg = "System package " + ps.name
1216 + " no longer exists; wiping its data";
1217 reportSettingsProblem(Log.WARN, msg);
Dianne Hackborn4428e172012-08-24 17:43:05 -07001218 removeDataDirsLI(ps.name);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001219 } else {
Kenny Root87b5d7b2012-05-16 13:36:18 -07001220 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
1221 if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
1222 possiblyDeletedUpdatedSystemApps.add(ps.name);
1223 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001224 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001225 }
1226 }
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 //look for any incomplete package installations
Kenny Root447106f2011-03-23 11:00:15 -07001229 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 //clean up list
1231 for(int i = 0; i < deletePkgsList.size(); i++) {
1232 //clean up here
1233 cleanupInstallFailedPackage(deletePkgsList.get(i));
1234 }
1235 //delete tmp files
1236 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001237
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001238 if (!mOnlyCore) {
1239 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1240 SystemClock.uptimeMillis());
1241 mAppInstallObserver = new AppDirObserver(
1242 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1243 mAppInstallObserver.startWatching();
1244 scanDirLI(mAppInstallDir, 0, scanMode, 0);
1245
1246 mDrmAppInstallObserver = new AppDirObserver(
1247 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1248 mDrmAppInstallObserver.startWatching();
1249 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1250 scanMode, 0);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001251
1252 /**
Kenny Root87b5d7b2012-05-16 13:36:18 -07001253 * Remove disable package settings for any updated system
1254 * apps that were removed via an OTA. If they're not a
1255 * previously-updated app, remove them completely.
1256 * Otherwise, just revoke their system-level permissions.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001257 */
Kenny Root87b5d7b2012-05-16 13:36:18 -07001258 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001259 PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
Kenny Root87b5d7b2012-05-16 13:36:18 -07001260 mSettings.removeDisabledSystemPackageLPw(deletedAppName);
1261
1262 String msg;
1263 if (deletedPkg == null) {
1264 msg = "Updated system package " + deletedAppName
1265 + " no longer exists; wiping its data";
Dianne Hackborn4428e172012-08-24 17:43:05 -07001266 removeDataDirsLI(deletedAppName);
Kenny Root87b5d7b2012-05-16 13:36:18 -07001267 } else {
1268 msg = "Updated system app + " + deletedAppName
1269 + " no longer present; removing system privileges for "
1270 + deletedAppName;
1271
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001272 deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
1273
1274 PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
1275 deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
1276 }
Kenny Root87b5d7b2012-05-16 13:36:18 -07001277 reportSettingsProblem(Log.WARN, msg);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001278 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001279 } else {
1280 mAppInstallObserver = null;
1281 mDrmAppInstallObserver = null;
1282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001284 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001286 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1288 + " seconds");
1289
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001290 // If the platform SDK has changed since the last time we booted,
1291 // we need to re-grant app permission to catch any new ones that
1292 // appear. This is really a hack, and means that apps can in some
1293 // cases get permissions that the user didn't initially explicitly
1294 // allow... it would be nice to have some better way to handle
1295 // this situation.
1296 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1297 != mSdkVersion;
1298 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1299 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1300 + "; regranting permissions for internal storage");
1301 mSettings.mInternalSdkPlatform = mSdkVersion;
1302
Dianne Hackborne639da72012-02-21 15:11:13 -08001303 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
1304 | (regrantPermissions
1305 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
1306 : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307
Kenny Root447106f2011-03-23 11:00:15 -07001308 // can downgrade to reader
1309 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001311 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 // Now after opening every single application zip, make sure they
1315 // are all flushed. Not really needed, but keeps things nice and
1316 // tidy.
1317 Runtime.getRuntime().gc();
Kenny Root05ca4c92011-09-15 10:36:25 -07001318
1319 mRequiredVerifierPackage = getRequiredVerifierLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 } // synchronized (mPackages)
1321 } // synchronized (mInstallLock)
1322 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001323
Dianne Hackborn58f42a52011-10-10 13:46:34 -07001324 public boolean isFirstBoot() {
1325 return !mRestoredSettings;
1326 }
1327
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001328 public boolean isOnlyCoreApps() {
1329 return mOnlyCore;
1330 }
1331
Kenny Root05ca4c92011-09-15 10:36:25 -07001332 private String getRequiredVerifierLPr() {
1333 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1334 final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
Amith Yamasani483f3b02012-03-13 16:08:00 -07001335 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07001336
1337 String requiredVerifier = null;
1338
1339 final int N = receivers.size();
1340 for (int i = 0; i < N; i++) {
1341 final ResolveInfo info = receivers.get(i);
1342
1343 if (info.activityInfo == null) {
1344 continue;
1345 }
1346
1347 final String packageName = info.activityInfo.packageName;
1348
1349 final PackageSetting ps = mSettings.mPackages.get(packageName);
1350 if (ps == null) {
1351 continue;
1352 }
1353
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001354 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1355 if (!gp.grantedPermissions
Kenny Root05ca4c92011-09-15 10:36:25 -07001356 .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
1357 continue;
1358 }
1359
1360 if (requiredVerifier != null) {
1361 throw new RuntimeException("There can be only one required verifier");
1362 }
1363
1364 requiredVerifier = packageName;
1365 }
1366
1367 return requiredVerifier;
1368 }
1369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 @Override
1371 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1372 throws RemoteException {
1373 try {
1374 return super.onTransact(code, data, reply, flags);
1375 } catch (RuntimeException e) {
1376 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001377 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 }
1379 throw e;
1380 }
1381 }
1382
Dianne Hackborne6620b22010-01-22 14:46:21 -08001383 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001384 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
Dianne Hackborn4428e172012-08-24 17:43:05 -07001385 removeDataDirsLI(ps.name);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001386 if (ps.codePath != null) {
1387 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001388 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001389 }
1390 }
1391 if (ps.resourcePath != null) {
1392 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001393 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001394 }
1395 }
Kenny Root447106f2011-03-23 11:00:15 -07001396 mSettings.removePackageLPw(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
1398
1399 void readPermissions() {
1400 // Read permissions from .../etc/permission directory.
1401 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1402 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001403 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 return;
1405 }
1406 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001407 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 return;
1409 }
1410
1411 // Iterate over the files in the directory and scan .xml files
1412 for (File f : libraryDir.listFiles()) {
1413 // We'll read platform.xml last
1414 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1415 continue;
1416 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001419 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 continue;
1421 }
1422 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001423 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 continue;
1425 }
1426
1427 readPermissionsFromXml(f);
1428 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1431 final File permFile = new File(Environment.getRootDirectory(),
1432 "etc/permissions/platform.xml");
1433 readPermissionsFromXml(permFile);
1434 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001435
1436 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 FileReader permReader = null;
1438 try {
1439 permReader = new FileReader(permFile);
1440 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001441 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 return;
1443 }
1444
1445 try {
1446 XmlPullParser parser = Xml.newPullParser();
1447 parser.setInput(permReader);
1448
1449 XmlUtils.beginDocument(parser, "permissions");
1450
1451 while (true) {
1452 XmlUtils.nextElement(parser);
1453 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1454 break;
1455 }
1456
1457 String name = parser.getName();
1458 if ("group".equals(name)) {
1459 String gidStr = parser.getAttributeValue(null, "gid");
1460 if (gidStr != null) {
Romain Guy01d159d2013-02-25 13:22:42 -08001461 int gid = Process.getGidForName(gidStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 mGlobalGids = appendInt(mGlobalGids, gid);
1463 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001464 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 + parser.getPositionDescription());
1466 }
1467
1468 XmlUtils.skipCurrentTag(parser);
1469 continue;
1470 } else if ("permission".equals(name)) {
1471 String perm = parser.getAttributeValue(null, "name");
1472 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001473 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 + parser.getPositionDescription());
1475 XmlUtils.skipCurrentTag(parser);
1476 continue;
1477 }
1478 perm = perm.intern();
1479 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 } else if ("assign-permission".equals(name)) {
1482 String perm = parser.getAttributeValue(null, "name");
1483 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001484 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 + parser.getPositionDescription());
1486 XmlUtils.skipCurrentTag(parser);
1487 continue;
1488 }
1489 String uidStr = parser.getAttributeValue(null, "uid");
1490 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001491 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 + parser.getPositionDescription());
1493 XmlUtils.skipCurrentTag(parser);
1494 continue;
1495 }
1496 int uid = Process.getUidForName(uidStr);
1497 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001498 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 + uidStr + "\" at "
1500 + parser.getPositionDescription());
1501 XmlUtils.skipCurrentTag(parser);
1502 continue;
1503 }
1504 perm = perm.intern();
1505 HashSet<String> perms = mSystemPermissions.get(uid);
1506 if (perms == null) {
1507 perms = new HashSet<String>();
1508 mSystemPermissions.put(uid, perms);
1509 }
1510 perms.add(perm);
1511 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 } else if ("library".equals(name)) {
1514 String lname = parser.getAttributeValue(null, "name");
1515 String lfile = parser.getAttributeValue(null, "file");
1516 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001517 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 + parser.getPositionDescription());
1519 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001520 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 + parser.getPositionDescription());
1522 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001523 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001524 mSharedLibraries.put(lname, lfile);
1525 }
1526 XmlUtils.skipCurrentTag(parser);
1527 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001528
Dianne Hackborn49237342009-08-27 20:08:01 -07001529 } else if ("feature".equals(name)) {
1530 String fname = parser.getAttributeValue(null, "name");
1531 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001532 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001533 + parser.getPositionDescription());
1534 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001535 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001536 FeatureInfo fi = new FeatureInfo();
1537 fi.name = fname;
1538 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540 XmlUtils.skipCurrentTag(parser);
1541 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 } else {
1544 XmlUtils.skipCurrentTag(parser);
1545 continue;
1546 }
1547
1548 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001549 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001551 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001553 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
1555 }
1556
1557 void readPermission(XmlPullParser parser, String name)
1558 throws IOException, XmlPullParserException {
1559
1560 name = name.intern();
1561
1562 BasePermission bp = mSettings.mPermissions.get(name);
1563 if (bp == null) {
1564 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1565 mSettings.mPermissions.put(name, bp);
1566 }
1567 int outerDepth = parser.getDepth();
1568 int type;
1569 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1570 && (type != XmlPullParser.END_TAG
1571 || parser.getDepth() > outerDepth)) {
1572 if (type == XmlPullParser.END_TAG
1573 || type == XmlPullParser.TEXT) {
1574 continue;
1575 }
1576
1577 String tagName = parser.getName();
1578 if ("group".equals(tagName)) {
1579 String gidStr = parser.getAttributeValue(null, "gid");
1580 if (gidStr != null) {
1581 int gid = Process.getGidForName(gidStr);
1582 bp.gids = appendInt(bp.gids, gid);
1583 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001584 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 + parser.getPositionDescription());
1586 }
1587 }
1588 XmlUtils.skipCurrentTag(parser);
1589 }
1590 }
1591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 static int[] appendInts(int[] cur, int[] add) {
1593 if (add == null) return cur;
1594 if (cur == null) return add;
1595 final int N = add.length;
1596 for (int i=0; i<N; i++) {
1597 cur = appendInt(cur, add[i]);
1598 }
1599 return cur;
1600 }
1601
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001602 static int[] removeInts(int[] cur, int[] rem) {
1603 if (rem == null) return cur;
1604 if (cur == null) return cur;
1605 final int N = rem.length;
1606 for (int i=0; i<N; i++) {
1607 cur = removeInt(cur, rem[i]);
1608 }
1609 return cur;
1610 }
1611
Amith Yamasani13593602012-03-22 16:16:17 -07001612 PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
1613 if (!sUserManager.exists(userId)) return null;
1614 PackageInfo pi;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001615 final PackageSetting ps = (PackageSetting) p.mExtras;
1616 if (ps == null) {
1617 return null;
1618 }
1619 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1620 final PackageUserState state = ps.readUserState(userId);
1621 pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
1622 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
1623 state, userId);
1624 if (pi != null) {
1625 pi.applicationInfo.enabledSetting = state.enabled;
Amith Yamasani13593602012-03-22 16:16:17 -07001626 pi.applicationInfo.enabled =
1627 pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
1628 || pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001629 }
Amith Yamasani13593602012-03-22 16:16:17 -07001630 return pi;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 }
1632
Amith Yamasani483f3b02012-03-13 16:08:00 -07001633 @Override
1634 public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001635 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001636 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package info");
Kenny Root447106f2011-03-23 11:00:15 -07001637 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 synchronized (mPackages) {
1639 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001640 if (DEBUG_PACKAGE_INFO)
1641 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001643 return generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 }
1645 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001646 return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 }
1648 }
1649 return null;
1650 }
1651
Dianne Hackborn47096932010-02-11 15:57:09 -08001652 public String[] currentToCanonicalPackageNames(String[] names) {
1653 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001654 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001655 synchronized (mPackages) {
1656 for (int i=names.length-1; i>=0; i--) {
1657 PackageSetting ps = mSettings.mPackages.get(names[i]);
1658 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1659 }
1660 }
1661 return out;
1662 }
1663
1664 public String[] canonicalToCurrentPackageNames(String[] names) {
1665 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001666 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001667 synchronized (mPackages) {
1668 for (int i=names.length-1; i>=0; i--) {
1669 String cur = mSettings.mRenamedPackages.get(names[i]);
1670 out[i] = cur != null ? cur : names[i];
1671 }
1672 }
1673 return out;
1674 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07001675
1676 @Override
1677 public int getPackageUid(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001678 if (!sUserManager.exists(userId)) return -1;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001679 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package uid");
Kenny Root447106f2011-03-23 11:00:15 -07001680 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 synchronized (mPackages) {
1682 PackageParser.Package p = mPackages.get(packageName);
1683 if(p != null) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001684 return UserHandle.getUid(userId, p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 }
1686 PackageSetting ps = mSettings.mPackages.get(packageName);
1687 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1688 return -1;
1689 }
1690 p = ps.pkg;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001691 return p != null ? UserHandle.getUid(userId, p.applicationInfo.uid) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 }
1693 }
1694
1695 public int[] getPackageGids(String packageName) {
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -07001696 final boolean enforcedDefault = isPermissionEnforcedDefault(READ_EXTERNAL_STORAGE);
Kenny Root447106f2011-03-23 11:00:15 -07001697 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 synchronized (mPackages) {
1699 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001700 if (DEBUG_PACKAGE_INFO)
1701 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 if (p != null) {
1703 final PackageSetting ps = (PackageSetting)p.mExtras;
1704 final SharedUserSetting suid = ps.sharedUser;
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07001705 int[] gids = suid != null ? suid.gids : ps.gids;
1706
1707 // include GIDs for any unenforced permissions
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -07001708 if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE, enforcedDefault)) {
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07001709 final BasePermission basePerm = mSettings.mPermissions.get(
1710 READ_EXTERNAL_STORAGE);
1711 gids = appendInts(gids, basePerm.gids);
1712 }
1713
1714 return gids;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 }
1716 }
1717 // stupid thing to indicate an error.
1718 return new int[0];
1719 }
1720
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001721 static final PermissionInfo generatePermissionInfo(
1722 BasePermission bp, int flags) {
1723 if (bp.perm != null) {
1724 return PackageParser.generatePermissionInfo(bp.perm, flags);
1725 }
1726 PermissionInfo pi = new PermissionInfo();
1727 pi.name = bp.name;
1728 pi.packageName = bp.sourcePackage;
1729 pi.nonLocalizedLabel = bp.name;
1730 pi.protectionLevel = bp.protectionLevel;
1731 return pi;
1732 }
1733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 public PermissionInfo getPermissionInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001735 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 synchronized (mPackages) {
1737 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001738 if (p != null) {
1739 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 }
1741 return null;
1742 }
1743 }
1744
1745 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001746 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 synchronized (mPackages) {
1748 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1749 for (BasePermission p : mSettings.mPermissions.values()) {
1750 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001751 if (p.perm == null || p.perm.info.group == null) {
1752 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 }
1754 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001755 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1757 }
1758 }
1759 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 if (out.size() > 0) {
1762 return out;
1763 }
1764 return mPermissionGroups.containsKey(group) ? out : null;
1765 }
1766 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001769 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 synchronized (mPackages) {
1771 return PackageParser.generatePermissionGroupInfo(
1772 mPermissionGroups.get(name), flags);
1773 }
1774 }
1775
1776 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001777 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 synchronized (mPackages) {
1779 final int N = mPermissionGroups.size();
1780 ArrayList<PermissionGroupInfo> out
1781 = new ArrayList<PermissionGroupInfo>(N);
1782 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1783 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1784 }
1785 return out;
1786 }
1787 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001788
Amith Yamasani483f3b02012-03-13 16:08:00 -07001789 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
1790 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001791 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001793 if (ps != null) {
1794 if (ps.pkg == null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001795 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName,
1796 flags, userId);
Kenny Root447106f2011-03-23 11:00:15 -07001797 if (pInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 return pInfo.applicationInfo;
1799 }
1800 return null;
1801 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001802 return PackageParser.generateApplicationInfo(ps.pkg, flags,
1803 ps.readUserState(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 }
1805 return null;
1806 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001807
Amith Yamasani483f3b02012-03-13 16:08:00 -07001808 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
1809 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001810 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001812 if (ps != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001813 PackageParser.Package pkg = ps.pkg;
1814 if (pkg == null) {
1815 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
1816 return null;
1817 }
1818 pkg = new PackageParser.Package(packageName);
1819 pkg.applicationInfo.packageName = packageName;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07001820 pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001821 pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1822 pkg.applicationInfo.sourceDir = ps.codePathString;
1823 pkg.applicationInfo.dataDir =
Amith Yamasani317046a2012-08-29 18:48:08 -07001824 getDataPathForPackage(packageName, 0).getPath();
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001825 pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001827 // pkg.mSetEnabled = ps.getEnabled(userId);
1828 // pkg.mSetStopped = ps.getStopped(userId);
1829 return generatePackageInfo(pkg, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 }
1831 return null;
1832 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001833
Amith Yamasani483f3b02012-03-13 16:08:00 -07001834 @Override
1835 public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001836 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001837 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get application info");
Kenny Root447106f2011-03-23 11:00:15 -07001838 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 synchronized (mPackages) {
1840 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001841 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 TAG, "getApplicationInfo " + packageName
1843 + ": " + p);
1844 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001845 PackageSetting ps = mSettings.mPackages.get(packageName);
1846 if (ps == null) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 // Note: isEnabledLP() does not apply here - always return info
Jeff Sharkey38f86882012-10-11 16:10:23 -07001848 return PackageParser.generateApplicationInfo(
1849 p, flags, ps.readUserState(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 }
1851 if ("android".equals(packageName)||"system".equals(packageName)) {
1852 return mAndroidApplication;
1853 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001854 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001855 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857 }
1858 return null;
1859 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001860
1861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1863 mContext.enforceCallingOrSelfPermission(
1864 android.Manifest.permission.CLEAR_APP_CACHE, null);
1865 // Queue up an async operation since clearing cache may take a little while.
1866 mHandler.post(new Runnable() {
1867 public void run() {
1868 mHandler.removeCallbacks(this);
1869 int retCode = -1;
Dianne Hackborn4428e172012-08-24 17:43:05 -07001870 synchronized (mInstallLock) {
1871 retCode = mInstaller.freeCache(freeStorageSize);
1872 if (retCode < 0) {
1873 Slog.w(TAG, "Couldn't clear application caches");
1874 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 if (observer != null) {
1877 try {
1878 observer.onRemoveCompleted(null, (retCode >= 0));
1879 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001880 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 }
1882 }
1883 }
1884 });
1885 }
1886
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001887 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001888 mContext.enforceCallingOrSelfPermission(
1889 android.Manifest.permission.CLEAR_APP_CACHE, null);
1890 // Queue up an async operation since clearing cache may take a little while.
1891 mHandler.post(new Runnable() {
1892 public void run() {
1893 mHandler.removeCallbacks(this);
1894 int retCode = -1;
Dianne Hackborn4428e172012-08-24 17:43:05 -07001895 synchronized (mInstallLock) {
1896 retCode = mInstaller.freeCache(freeStorageSize);
1897 if (retCode < 0) {
1898 Slog.w(TAG, "Couldn't clear application caches");
1899 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001900 }
1901 if(pi != null) {
1902 try {
1903 // Callback via pending intent
1904 int code = (retCode >= 0) ? 1 : 0;
1905 pi.sendIntent(null, code, null,
1906 null, null);
1907 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001908 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001909 }
1910 }
1911 }
1912 });
1913 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001914
Amith Yamasani483f3b02012-03-13 16:08:00 -07001915 @Override
1916 public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001917 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001918 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get activity info");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001919 synchronized (mPackages) {
1920 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001921
Kenny Root9718cf52011-02-23 16:45:26 -08001922 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001923 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001924 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1925 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001926 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
1927 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 }
1929 if (mResolveComponentName.equals(component)) {
1930 return mResolveActivity;
1931 }
1932 }
1933 return null;
1934 }
1935
Amith Yamasani483f3b02012-03-13 16:08:00 -07001936 @Override
1937 public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001938 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001939 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get receiver info");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 synchronized (mPackages) {
1941 PackageParser.Activity a = mReceivers.mActivities.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001942 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 TAG, "getReceiverInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001944 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001945 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1946 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001947 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
1948 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 }
1950 }
1951 return null;
1952 }
1953
Amith Yamasani483f3b02012-03-13 16:08:00 -07001954 @Override
1955 public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001956 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001957 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get service info");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 synchronized (mPackages) {
1959 PackageParser.Service s = mServices.mServices.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001960 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 TAG, "getServiceInfo " + component + ": " + s);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001962 if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001963 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1964 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001965 return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
1966 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 }
1968 }
1969 return null;
1970 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001971
Amith Yamasani483f3b02012-03-13 16:08:00 -07001972 @Override
1973 public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001974 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07001975 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info");
Dianne Hackborn361199b2010-08-30 17:42:07 -07001976 synchronized (mPackages) {
1977 PackageParser.Provider p = mProvidersByComponent.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001978 if (DEBUG_PACKAGE_INFO) Log.v(
Dianne Hackborn361199b2010-08-30 17:42:07 -07001979 TAG, "getProviderInfo " + component + ": " + p);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001980 if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001981 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1982 if (ps == null) return null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001983 return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
1984 userId);
Dianne Hackborn361199b2010-08-30 17:42:07 -07001985 }
1986 }
1987 return null;
1988 }
1989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 public String[] getSystemSharedLibraryNames() {
1991 Set<String> libSet;
1992 synchronized (mPackages) {
1993 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001994 int size = libSet.size();
1995 if (size > 0) {
1996 String[] libs = new String[size];
1997 libSet.toArray(libs);
1998 return libs;
1999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002001 return null;
2002 }
2003
2004 public FeatureInfo[] getSystemAvailableFeatures() {
2005 Collection<FeatureInfo> featSet;
2006 synchronized (mPackages) {
2007 featSet = mAvailableFeatures.values();
2008 int size = featSet.size();
2009 if (size > 0) {
2010 FeatureInfo[] features = new FeatureInfo[size+1];
2011 featSet.toArray(features);
2012 FeatureInfo fi = new FeatureInfo();
2013 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
2014 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2015 features[size] = fi;
2016 return features;
2017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 }
2019 return null;
2020 }
2021
Dianne Hackborn039c68e2009-09-26 16:39:23 -07002022 public boolean hasSystemFeature(String name) {
2023 synchronized (mPackages) {
2024 return mAvailableFeatures.containsKey(name);
2025 }
2026 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002027
Amith Yamasani483f3b02012-03-13 16:08:00 -07002028 private void checkValidCaller(int uid, int userId) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002029 if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
Amith Yamasani483f3b02012-03-13 16:08:00 -07002030 return;
2031
2032 throw new SecurityException("Caller uid=" + uid
2033 + " is not privileged to communicate with user=" + userId);
2034 }
2035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036 public int checkPermission(String permName, String pkgName) {
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -07002037 final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 synchronized (mPackages) {
2039 PackageParser.Package p = mPackages.get(pkgName);
2040 if (p != null && p.mExtras != null) {
2041 PackageSetting ps = (PackageSetting)p.mExtras;
2042 if (ps.sharedUser != null) {
2043 if (ps.sharedUser.grantedPermissions.contains(permName)) {
2044 return PackageManager.PERMISSION_GRANTED;
2045 }
2046 } else if (ps.grantedPermissions.contains(permName)) {
2047 return PackageManager.PERMISSION_GRANTED;
2048 }
2049 }
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -07002050 if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07002051 return PackageManager.PERMISSION_GRANTED;
2052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 }
2054 return PackageManager.PERMISSION_DENIED;
2055 }
2056
2057 public int checkUidPermission(String permName, int uid) {
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -07002058 final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 synchronized (mPackages) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002060 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002062 GrantedPermissions gp = (GrantedPermissions)obj;
2063 if (gp.grantedPermissions.contains(permName)) {
2064 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 }
2066 } else {
2067 HashSet<String> perms = mSystemPermissions.get(uid);
2068 if (perms != null && perms.contains(permName)) {
2069 return PackageManager.PERMISSION_GRANTED;
2070 }
2071 }
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -07002072 if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07002073 return PackageManager.PERMISSION_GRANTED;
2074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 }
2076 return PackageManager.PERMISSION_DENIED;
2077 }
2078
Amith Yamasanif203aee2012-08-29 18:41:53 -07002079 /**
2080 * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
2081 * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
2082 * @param message the message to log on security exception
2083 * @return
2084 */
2085 private void enforceCrossUserPermission(int callingUid, int userId,
2086 boolean requireFullPermission, String message) {
2087 if (userId < 0) {
2088 throw new IllegalArgumentException("Invalid userId " + userId);
2089 }
2090 if (userId == UserHandle.getUserId(callingUid)) return;
2091 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
2092 if (requireFullPermission) {
2093 mContext.enforceCallingOrSelfPermission(
2094 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
2095 } else {
2096 try {
2097 mContext.enforceCallingOrSelfPermission(
2098 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
2099 } catch (SecurityException se) {
2100 mContext.enforceCallingOrSelfPermission(
2101 android.Manifest.permission.INTERACT_ACROSS_USERS, message);
2102 }
2103 }
2104 }
2105 }
2106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 private BasePermission findPermissionTreeLP(String permName) {
2108 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
2109 if (permName.startsWith(bp.name) &&
2110 permName.length() > bp.name.length() &&
2111 permName.charAt(bp.name.length()) == '.') {
2112 return bp;
2113 }
2114 }
2115 return null;
2116 }
2117
2118 private BasePermission checkPermissionTreeLP(String permName) {
2119 if (permName != null) {
2120 BasePermission bp = findPermissionTreeLP(permName);
2121 if (bp != null) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002122 if (bp.uid == UserHandle.getAppId(Binder.getCallingUid())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 return bp;
2124 }
2125 throw new SecurityException("Calling uid "
2126 + Binder.getCallingUid()
2127 + " is not allowed to add to permission tree "
2128 + bp.name + " owned by uid " + bp.uid);
2129 }
2130 }
2131 throw new SecurityException("No permission tree found for " + permName);
2132 }
2133
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002134 static boolean compareStrings(CharSequence s1, CharSequence s2) {
2135 if (s1 == null) {
2136 return s2 == null;
2137 }
2138 if (s2 == null) {
2139 return false;
2140 }
2141 if (s1.getClass() != s2.getClass()) {
2142 return false;
2143 }
2144 return s1.equals(s2);
2145 }
2146
2147 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
2148 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07002149 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002150 if (pi1.protectionLevel != pi2.protectionLevel) return false;
2151 if (!compareStrings(pi1.name, pi2.name)) return false;
2152 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
2153 // We'll take care of setting this one.
2154 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
2155 // These are not currently stored in settings.
2156 //if (!compareStrings(pi1.group, pi2.group)) return false;
2157 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
2158 //if (pi1.labelRes != pi2.labelRes) return false;
2159 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
2160 return true;
2161 }
2162
2163 boolean addPermissionLocked(PermissionInfo info, boolean async) {
2164 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
2165 throw new SecurityException("Label must be specified in permission");
2166 }
2167 BasePermission tree = checkPermissionTreeLP(info.name);
2168 BasePermission bp = mSettings.mPermissions.get(info.name);
2169 boolean added = bp == null;
2170 boolean changed = true;
Dianne Hackborne639da72012-02-21 15:11:13 -08002171 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002172 if (added) {
2173 bp = new BasePermission(info.name, tree.sourcePackage,
2174 BasePermission.TYPE_DYNAMIC);
2175 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
2176 throw new SecurityException(
2177 "Not allowed to modify non-dynamic permission "
2178 + info.name);
2179 } else {
Dianne Hackborne639da72012-02-21 15:11:13 -08002180 if (bp.protectionLevel == fixedLevel
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002181 && bp.perm.owner.equals(tree.perm.owner)
2182 && bp.uid == tree.uid
2183 && comparePermissionInfos(bp.perm.info, info)) {
2184 changed = false;
2185 }
2186 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002187 bp.protectionLevel = fixedLevel;
2188 info = new PermissionInfo(info);
2189 info.protectionLevel = fixedLevel;
2190 bp.perm = new PackageParser.Permission(tree.perm.owner, info);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002191 bp.perm.info.packageName = tree.perm.info.packageName;
2192 bp.uid = tree.uid;
2193 if (added) {
2194 mSettings.mPermissions.put(info.name, bp);
2195 }
2196 if (changed) {
2197 if (!async) {
Kenny Root447106f2011-03-23 11:00:15 -07002198 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002199 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002200 scheduleWriteSettingsLocked();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002201 }
2202 }
2203 return added;
2204 }
2205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 public boolean addPermission(PermissionInfo info) {
2207 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002208 return addPermissionLocked(info, false);
2209 }
2210 }
2211
2212 public boolean addPermissionAsync(PermissionInfo info) {
2213 synchronized (mPackages) {
2214 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 }
2216 }
2217
2218 public void removePermission(String name) {
2219 synchronized (mPackages) {
2220 checkPermissionTreeLP(name);
2221 BasePermission bp = mSettings.mPermissions.get(name);
2222 if (bp != null) {
2223 if (bp.type != BasePermission.TYPE_DYNAMIC) {
2224 throw new SecurityException(
2225 "Not allowed to modify non-dynamic permission "
2226 + name);
2227 }
2228 mSettings.mPermissions.remove(name);
Kenny Root447106f2011-03-23 11:00:15 -07002229 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 }
2231 }
2232 }
2233
Dianne Hackborne639da72012-02-21 15:11:13 -08002234 public void grantPermission(String packageName, String permissionName) {
2235 mContext.enforceCallingOrSelfPermission(
2236 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2237 synchronized (mPackages) {
2238 final PackageParser.Package pkg = mPackages.get(packageName);
2239 if (pkg == null) {
2240 throw new IllegalArgumentException("Unknown package: " + packageName);
2241 }
2242 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2243 if (bp == null) {
2244 throw new IllegalArgumentException("Unknown permission: " + packageName);
2245 }
2246 if (!pkg.requestedPermissions.contains(permissionName)) {
2247 throw new SecurityException("Package " + packageName
2248 + " has not requested permission " + permissionName);
2249 }
2250 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2251 throw new SecurityException("Permission " + permissionName
2252 + " is not a development permission");
2253 }
2254 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2255 if (ps == null) {
2256 return;
2257 }
2258 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2259 if (gp.grantedPermissions.add(permissionName)) {
2260 if (ps.haveGids) {
2261 gp.gids = appendInts(gp.gids, bp.gids);
2262 }
2263 mSettings.writeLPr();
2264 }
2265 }
2266 }
2267
2268 public void revokePermission(String packageName, String permissionName) {
2269 synchronized (mPackages) {
2270 final PackageParser.Package pkg = mPackages.get(packageName);
2271 if (pkg == null) {
2272 throw new IllegalArgumentException("Unknown package: " + packageName);
2273 }
2274 if (pkg.applicationInfo.uid != Binder.getCallingUid()) {
2275 mContext.enforceCallingOrSelfPermission(
2276 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2277 }
2278 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2279 if (bp == null) {
2280 throw new IllegalArgumentException("Unknown permission: " + packageName);
2281 }
2282 if (!pkg.requestedPermissions.contains(permissionName)) {
2283 throw new SecurityException("Package " + packageName
2284 + " has not requested permission " + permissionName);
2285 }
2286 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2287 throw new SecurityException("Permission " + permissionName
2288 + " is not a development permission");
2289 }
2290 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2291 if (ps == null) {
2292 return;
2293 }
2294 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2295 if (gp.grantedPermissions.remove(permissionName)) {
2296 gp.grantedPermissions.remove(permissionName);
2297 if (ps.haveGids) {
2298 gp.gids = removeInts(gp.gids, bp.gids);
2299 }
2300 mSettings.writeLPr();
2301 }
2302 }
2303 }
2304
Dianne Hackborn854060af2009-07-09 18:14:31 -07002305 public boolean isProtectedBroadcast(String actionName) {
2306 synchronized (mPackages) {
2307 return mProtectedBroadcasts.contains(actionName);
2308 }
2309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 public int checkSignatures(String pkg1, String pkg2) {
2312 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002313 final PackageParser.Package p1 = mPackages.get(pkg1);
2314 final PackageParser.Package p2 = mPackages.get(pkg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 if (p1 == null || p1.mExtras == null
2316 || p2 == null || p2.mExtras == null) {
2317 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2318 }
Kenny Root447106f2011-03-23 11:00:15 -07002319 return compareSignatures(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 }
2321 }
2322
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002323 public int checkUidSignatures(int uid1, int uid2) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002324 // Map to base uids.
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002325 uid1 = UserHandle.getAppId(uid1);
2326 uid2 = UserHandle.getAppId(uid2);
Kenny Root447106f2011-03-23 11:00:15 -07002327 // reader
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002328 synchronized (mPackages) {
2329 Signature[] s1;
2330 Signature[] s2;
Kenny Root447106f2011-03-23 11:00:15 -07002331 Object obj = mSettings.getUserIdLPr(uid1);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002332 if (obj != null) {
2333 if (obj instanceof SharedUserSetting) {
2334 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
2335 } else if (obj instanceof PackageSetting) {
2336 s1 = ((PackageSetting)obj).signatures.mSignatures;
2337 } else {
2338 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2339 }
2340 } else {
2341 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2342 }
Kenny Root447106f2011-03-23 11:00:15 -07002343 obj = mSettings.getUserIdLPr(uid2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002344 if (obj != null) {
2345 if (obj instanceof SharedUserSetting) {
2346 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
2347 } else if (obj instanceof PackageSetting) {
2348 s2 = ((PackageSetting)obj).signatures.mSignatures;
2349 } else {
2350 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2351 }
2352 } else {
2353 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2354 }
Kenny Root447106f2011-03-23 11:00:15 -07002355 return compareSignatures(s1, s2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002356 }
2357 }
2358
Kenny Root447106f2011-03-23 11:00:15 -07002359 static int compareSignatures(Signature[] s1, Signature[] s2) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002360 if (s1 == null) {
2361 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 ? PackageManager.SIGNATURE_NEITHER_SIGNED
2363 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
2364 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002365 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
2367 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002368 HashSet<Signature> set1 = new HashSet<Signature>();
2369 for (Signature sig : s1) {
2370 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002372 HashSet<Signature> set2 = new HashSet<Signature>();
2373 for (Signature sig : s2) {
2374 set2.add(sig);
2375 }
2376 // Make sure s2 contains all signatures in s1.
2377 if (set1.equals(set2)) {
2378 return PackageManager.SIGNATURE_MATCH;
2379 }
2380 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 }
2382
2383 public String[] getPackagesForUid(int uid) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002384 uid = UserHandle.getAppId(uid);
Kenny Root447106f2011-03-23 11:00:15 -07002385 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002387 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002389 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 final int N = sus.packages.size();
Kenny Root447106f2011-03-23 11:00:15 -07002391 final String[] res = new String[N];
2392 final Iterator<PackageSetting> it = sus.packages.iterator();
2393 int i = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 while (it.hasNext()) {
2395 res[i++] = it.next().name;
2396 }
2397 return res;
2398 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002399 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 return new String[] { ps.name };
2401 }
2402 }
2403 return null;
2404 }
2405
2406 public String getNameForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07002407 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 synchronized (mPackages) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002409 Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002411 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 return sus.name + ":" + sus.userId;
2413 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002414 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 return ps.name;
2416 }
2417 }
2418 return null;
2419 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 public int getUidForSharedUser(String sharedUserName) {
2422 if(sharedUserName == null) {
2423 return -1;
2424 }
Kenny Root447106f2011-03-23 11:00:15 -07002425 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002427 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
Amith Yamasani742a6712011-05-04 14:49:28 -07002428 if (suid == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 return -1;
2430 }
2431 return suid.userId;
2432 }
2433 }
2434
Amith Yamasani483f3b02012-03-13 16:08:00 -07002435 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002437 int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002438 if (!sUserManager.exists(userId)) return null;
Amith Yamasanif203aee2012-08-29 18:41:53 -07002439 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
Amith Yamasani483f3b02012-03-13 16:08:00 -07002440 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2441 return chooseBestActivity(intent, resolvedType, flags, query, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02002442 }
2443
Mihai Predaeae850c2009-05-13 10:13:48 +02002444 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002445 int flags, List<ResolveInfo> query, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 if (query != null) {
2447 final int N = query.size();
2448 if (N == 1) {
2449 return query.get(0);
2450 } else if (N > 1) {
2451 // If there is more than one activity with the same priority,
2452 // then let the user decide between them.
2453 ResolveInfo r0 = query.get(0);
2454 ResolveInfo r1 = query.get(1);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002455 if (DEBUG_INTENT_MATCHING) {
2456 Log.d(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
2457 + r1.activityInfo.name + "=" + r1.priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 }
2459 // If the first activity has a higher priority, or a different
2460 // default, then it is always desireable to pick it.
2461 if (r0.priority != r1.priority
2462 || r0.preferredOrder != r1.preferredOrder
2463 || r0.isDefault != r1.isDefault) {
2464 return query.get(0);
2465 }
2466 // If we have saved a preference for a preferred activity for
2467 // this Intent, use that.
2468 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002469 flags, query, r0.priority, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 if (ri != null) {
2471 return ri;
2472 }
Dianne Hackborn8da429e2012-09-23 12:52:19 -07002473 if (userId != 0) {
2474 ri = new ResolveInfo(mResolveInfo);
2475 ri.activityInfo = new ActivityInfo(ri.activityInfo);
2476 ri.activityInfo.applicationInfo = new ApplicationInfo(
2477 ri.activityInfo.applicationInfo);
2478 ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
2479 UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
2480 return ri;
2481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 return mResolveInfo;
2483 }
2484 }
2485 return null;
2486 }
2487
2488 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002489 int flags, List<ResolveInfo> query, int priority, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002490 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002491 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 synchronized (mPackages) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002493 if (intent.getSelector() != null) {
2494 intent = intent.getSelector();
2495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
Dianne Hackborn63092712012-10-07 14:45:35 -07002497 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
2498 List<PreferredActivity> prefs = pir != null
2499 ? pir.queryIntent(intent, resolvedType,
2500 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
2501 : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 if (prefs != null && prefs.size() > 0) {
2503 // First figure out how good the original match set is.
2504 // We will only allow preferred activities that came
2505 // from the same match quality.
2506 int match = 0;
Kenny Root447106f2011-03-23 11:00:15 -07002507
2508 if (DEBUG_PREFERRED) {
2509 Log.v(TAG, "Figuring out best match...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 }
Kenny Root447106f2011-03-23 11:00:15 -07002511
2512 final int N = query.size();
2513 for (int j=0; j<N; j++) {
2514 final ResolveInfo ri = query.get(j);
2515 if (DEBUG_PREFERRED) {
2516 Log.v(TAG, "Match for " + ri.activityInfo + ": 0x"
2517 + Integer.toHexString(match));
2518 }
2519 if (ri.match > match) {
2520 match = ri.match;
2521 }
2522 }
2523
2524 if (DEBUG_PREFERRED) {
2525 Log.v(TAG, "Best match: 0x" + Integer.toHexString(match));
2526 }
2527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 match &= IntentFilter.MATCH_CATEGORY_MASK;
2529 final int M = prefs.size();
2530 for (int i=0; i<M; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002531 final PreferredActivity pa = prefs.get(i);
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002532 if (pa.mPref.mMatch != match) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 continue;
2534 }
Dianne Hackborn77119bc2012-10-23 14:32:48 -07002535 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent,
2536 flags | PackageManager.GET_DISABLED_COMPONENTS, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 if (DEBUG_PREFERRED) {
2538 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002539 if (ai != null) {
2540 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2541 } else {
2542 Log.v(TAG, " null");
2543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002545 if (ai == null) {
2546 // This previously registered preferred activity
2547 // component is no longer known. Most likely an update
2548 // to the app was installed and in the new version this
2549 // component no longer exists. Clean it up by removing
2550 // it from the preferred activities list, and skip it.
2551 Slog.w(TAG, "Removing dangling preferred activity: "
2552 + pa.mPref.mComponent);
Dianne Hackborn63092712012-10-07 14:45:35 -07002553 pir.removeFilter(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -08002554 continue;
2555 }
2556 for (int j=0; j<N; j++) {
2557 final ResolveInfo ri = query.get(j);
2558 if (!ri.activityInfo.applicationInfo.packageName
2559 .equals(ai.applicationInfo.packageName)) {
2560 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002562 if (!ri.activityInfo.name.equals(ai.name)) {
2563 continue;
2564 }
2565
2566 // Okay we found a previously set preferred app.
2567 // If the result set is different from when this
2568 // was created, we need to clear it and re-ask the
2569 // user their preference.
2570 if (!pa.mPref.sameSet(query, priority)) {
2571 Slog.i(TAG, "Result set changed, dropping preferred activity for "
2572 + intent + " type " + resolvedType);
Dianne Hackborn63092712012-10-07 14:45:35 -07002573 pir.removeFilter(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -08002574 return null;
2575 }
2576
2577 // Yay!
2578 return ri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 }
2580 }
2581 }
2582 }
2583 return null;
2584 }
2585
Amith Yamasani483f3b02012-03-13 16:08:00 -07002586 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 public List<ResolveInfo> queryIntentActivities(Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002588 String resolvedType, int flags, int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002589 if (!sUserManager.exists(userId)) return Collections.emptyList();
Amith Yamasanif203aee2012-08-29 18:41:53 -07002590 enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities");
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002591 ComponentName comp = intent.getComponent();
2592 if (comp == null) {
2593 if (intent.getSelector() != null) {
2594 intent = intent.getSelector();
2595 comp = intent.getComponent();
2596 }
2597 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002600 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002601 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 if (ai != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002603 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 ri.activityInfo = ai;
2605 list.add(ri);
2606 }
2607 return list;
2608 }
2609
Kenny Root447106f2011-03-23 11:00:15 -07002610 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002612 final String pkgName = intent.getPackage();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002613 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002614 return mActivities.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002615 }
Kenny Root447106f2011-03-23 11:00:15 -07002616 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002617 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002618 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002619 pkg.activities, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002620 }
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08002621 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
2623 }
2624
Amith Yamasani483f3b02012-03-13 16:08:00 -07002625 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2627 Intent[] specifics, String[] specificTypes, Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002628 String resolvedType, int flags, int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002629 if (!sUserManager.exists(userId)) return Collections.emptyList();
Amith Yamasanif203aee2012-08-29 18:41:53 -07002630 enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
2631 "query intent activity options");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 final String resultsAction = intent.getAction();
2633
Kenny Root447106f2011-03-23 11:00:15 -07002634 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
Amith Yamasani483f3b02012-03-13 16:08:00 -07002635 | PackageManager.GET_RESOLVED_FILTER, userId);
Kenny Root447106f2011-03-23 11:00:15 -07002636
2637 if (DEBUG_INTENT_MATCHING) {
2638 Log.v(TAG, "Query " + intent + ": " + results);
2639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640
2641 int specificsPos = 0;
2642 int N;
2643
2644 // todo: note that the algorithm used here is O(N^2). This
2645 // isn't a problem in our current environment, but if we start running
2646 // into situations where we have more than 5 or 10 matches then this
2647 // should probably be changed to something smarter...
2648
2649 // First we go through and resolve each of the specific items
2650 // that were supplied, taking care of removing any corresponding
2651 // duplicate items in the generic resolve list.
2652 if (specifics != null) {
2653 for (int i=0; i<specifics.length; i++) {
2654 final Intent sintent = specifics[i];
2655 if (sintent == null) {
2656 continue;
2657 }
2658
Kenny Root447106f2011-03-23 11:00:15 -07002659 if (DEBUG_INTENT_MATCHING) {
2660 Log.v(TAG, "Specific #" + i + ": " + sintent);
2661 }
2662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 String action = sintent.getAction();
2664 if (resultsAction != null && resultsAction.equals(action)) {
2665 // If this action was explicitly requested, then don't
2666 // remove things that have it.
2667 action = null;
2668 }
Kenny Root447106f2011-03-23 11:00:15 -07002669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 ResolveInfo ri = null;
2671 ActivityInfo ai = null;
Kenny Root447106f2011-03-23 11:00:15 -07002672
2673 ComponentName comp = sintent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 if (comp == null) {
2675 ri = resolveIntent(
2676 sintent,
2677 specificTypes != null ? specificTypes[i] : null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002678 flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 if (ri == null) {
2680 continue;
2681 }
2682 if (ri == mResolveInfo) {
2683 // ACK! Must do something better with this.
2684 }
2685 ai = ri.activityInfo;
2686 comp = new ComponentName(ai.applicationInfo.packageName,
2687 ai.name);
2688 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002689 ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 if (ai == null) {
2691 continue;
2692 }
2693 }
2694
2695 // Look for any generic query activities that are duplicates
2696 // of this specific one, and remove them from the results.
Kenny Root9718cf52011-02-23 16:45:26 -08002697 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 N = results.size();
2699 int j;
2700 for (j=specificsPos; j<N; j++) {
2701 ResolveInfo sri = results.get(j);
2702 if ((sri.activityInfo.name.equals(comp.getClassName())
2703 && sri.activityInfo.applicationInfo.packageName.equals(
2704 comp.getPackageName()))
2705 || (action != null && sri.filter.matchAction(action))) {
2706 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002707 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 TAG, "Removing duplicate item from " + j
2709 + " due to specific " + specificsPos);
2710 if (ri == null) {
2711 ri = sri;
2712 }
2713 j--;
2714 N--;
2715 }
2716 }
2717
2718 // Add this specific item to its proper place.
2719 if (ri == null) {
2720 ri = new ResolveInfo();
2721 ri.activityInfo = ai;
2722 }
2723 results.add(specificsPos, ri);
2724 ri.specificIndex = i;
2725 specificsPos++;
2726 }
2727 }
2728
2729 // Now we go through the remaining generic results and remove any
2730 // duplicate actions that are found here.
2731 N = results.size();
2732 for (int i=specificsPos; i<N-1; i++) {
2733 final ResolveInfo rii = results.get(i);
2734 if (rii.filter == null) {
2735 continue;
2736 }
2737
2738 // Iterate over all of the actions of this result's intent
2739 // filter... typically this should be just one.
2740 final Iterator<String> it = rii.filter.actionsIterator();
2741 if (it == null) {
2742 continue;
2743 }
2744 while (it.hasNext()) {
2745 final String action = it.next();
2746 if (resultsAction != null && resultsAction.equals(action)) {
2747 // If this action was explicitly requested, then don't
2748 // remove things that have it.
2749 continue;
2750 }
2751 for (int j=i+1; j<N; j++) {
2752 final ResolveInfo rij = results.get(j);
2753 if (rij.filter != null && rij.filter.hasAction(action)) {
2754 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002755 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 TAG, "Removing duplicate item from " + j
2757 + " due to action " + action + " at " + i);
2758 j--;
2759 N--;
2760 }
2761 }
2762 }
2763
2764 // If the caller didn't request filter information, drop it now
2765 // so we don't have to marshall/unmarshall it.
2766 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2767 rii.filter = null;
2768 }
2769 }
2770
2771 // Filter out the caller activity if so requested.
2772 if (caller != null) {
2773 N = results.size();
2774 for (int i=0; i<N; i++) {
2775 ActivityInfo ainfo = results.get(i).activityInfo;
2776 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2777 && caller.getClassName().equals(ainfo.name)) {
2778 results.remove(i);
2779 break;
2780 }
2781 }
2782 }
2783
2784 // If the caller didn't request filter information,
2785 // drop them now so we don't have to
2786 // marshall/unmarshall it.
2787 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2788 N = results.size();
2789 for (int i=0; i<N; i++) {
2790 results.get(i).filter = null;
2791 }
2792 }
2793
Kenny Root9718cf52011-02-23 16:45:26 -08002794 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 return results;
2796 }
2797
Amith Yamasani483f3b02012-03-13 16:08:00 -07002798 @Override
2799 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
2800 int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002801 if (!sUserManager.exists(userId)) return Collections.emptyList();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002802 ComponentName comp = intent.getComponent();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002803 if (comp == null) {
2804 if (intent.getSelector() != null) {
2805 intent = intent.getSelector();
2806 comp = intent.getComponent();
2807 }
2808 }
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002809 if (comp != null) {
2810 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002811 ActivityInfo ai = getReceiverInfo(comp, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002812 if (ai != null) {
2813 ResolveInfo ri = new ResolveInfo();
2814 ri.activityInfo = ai;
2815 list.add(ri);
2816 }
2817 return list;
2818 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002819
Kenny Root447106f2011-03-23 11:00:15 -07002820 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002822 String pkgName = intent.getPackage();
2823 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002824 return mReceivers.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002825 }
Kenny Root447106f2011-03-23 11:00:15 -07002826 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002827 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002828 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
2829 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002830 }
2831 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 }
2833 }
2834
Amith Yamasani483f3b02012-03-13 16:08:00 -07002835 @Override
2836 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
2837 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07002838 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839 if (query != null) {
2840 if (query.size() >= 1) {
2841 // If there is more than one service with the same priority,
2842 // just arbitrarily pick the first one.
2843 return query.get(0);
2844 }
2845 }
2846 return null;
2847 }
2848
Amith Yamasani483f3b02012-03-13 16:08:00 -07002849 @Override
2850 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
2851 int userId) {
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002852 if (!sUserManager.exists(userId)) return Collections.emptyList();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002853 ComponentName comp = intent.getComponent();
2854 if (comp == null) {
2855 if (intent.getSelector() != null) {
2856 intent = intent.getSelector();
2857 comp = intent.getComponent();
2858 }
2859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002861 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002862 final ServiceInfo si = getServiceInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 if (si != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002864 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 ri.serviceInfo = si;
2866 list.add(ri);
2867 }
2868 return list;
2869 }
2870
Kenny Root447106f2011-03-23 11:00:15 -07002871 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002873 String pkgName = intent.getPackage();
2874 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002875 return mServices.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002876 }
Kenny Root447106f2011-03-23 11:00:15 -07002877 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002878 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002879 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
2880 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002881 }
2882 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
2884 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002885
Amith Yamasani151ec4c2012-09-07 19:25:16 -07002886 @Override
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002887 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002888 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani151ec4c2012-09-07 19:25:16 -07002889
2890 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891
Kenny Root447106f2011-03-23 11:00:15 -07002892 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 synchronized (mPackages) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002894 ArrayList<PackageInfo> list;
Kenny Root0e2c0f32011-04-15 17:50:10 -07002895 if (listUninstalled) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002896 list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
2897 for (PackageSetting ps : mSettings.mPackages.values()) {
2898 PackageInfo pi;
2899 if (ps.pkg != null) {
2900 pi = generatePackageInfo(ps.pkg, flags, userId);
2901 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002902 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002904 if (pi != null) {
2905 list.add(pi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 }
2907 }
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002908 } else {
2909 list = new ArrayList<PackageInfo>(mPackages.size());
2910 for (PackageParser.Package p : mPackages.values()) {
2911 PackageInfo pi = generatePackageInfo(p, flags, userId);
2912 if (pi != null) {
2913 list.add(pi);
2914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 }
2916 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002917
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002918 return new ParceledListSlice<PackageInfo>(list);
2919 }
2920 }
2921
2922 private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
2923 String[] permissions, boolean[] tmp, int flags, int userId) {
2924 int numMatch = 0;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002925 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002926 for (int i=0; i<permissions.length; i++) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002927 if (gp.grantedPermissions.contains(permissions[i])) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002928 tmp[i] = true;
2929 numMatch++;
2930 } else {
2931 tmp[i] = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 }
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002934 if (numMatch == 0) {
2935 return;
2936 }
2937 PackageInfo pi;
2938 if (ps.pkg != null) {
2939 pi = generatePackageInfo(ps.pkg, flags, userId);
2940 } else {
2941 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
2942 }
2943 if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
2944 if (numMatch == permissions.length) {
2945 pi.requestedPermissions = permissions;
2946 } else {
2947 pi.requestedPermissions = new String[numMatch];
2948 numMatch = 0;
2949 for (int i=0; i<permissions.length; i++) {
2950 if (tmp[i]) {
2951 pi.requestedPermissions[numMatch] = permissions[i];
2952 numMatch++;
2953 }
2954 }
2955 }
2956 }
2957 list.add(pi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 }
2959
Amith Yamasani483f3b02012-03-13 16:08:00 -07002960 @Override
Dianne Hackborne7991752013-01-16 17:56:46 -08002961 public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002962 String[] permissions, int flags, int userId) {
Dianne Hackborne7991752013-01-16 17:56:46 -08002963 if (!sUserManager.exists(userId)) return null;
Dianne Hackborne7991752013-01-16 17:56:46 -08002964 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2965
2966 // writer
2967 synchronized (mPackages) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002968 ArrayList<PackageInfo> list = new ArrayList<PackageInfo>();
2969 boolean[] tmpBools = new boolean[permissions.length];
Dianne Hackborne7991752013-01-16 17:56:46 -08002970 if (listUninstalled) {
2971 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002972 addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId);
Dianne Hackborne7991752013-01-16 17:56:46 -08002973 }
2974 } else {
2975 for (PackageParser.Package pkg : mPackages.values()) {
2976 PackageSetting ps = (PackageSetting)pkg.mExtras;
2977 if (ps != null) {
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08002978 addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
2979 userId);
2980 }
2981 }
2982 }
2983
2984 return new ParceledListSlice<PackageInfo>(list);
2985 }
2986 }
2987
2988 @Override
2989 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
2990 if (!sUserManager.exists(userId)) return null;
2991 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2992
2993 // writer
2994 synchronized (mPackages) {
2995 ArrayList<ApplicationInfo> list;
2996 if (listUninstalled) {
2997 list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
2998 for (PackageSetting ps : mSettings.mPackages.values()) {
2999 ApplicationInfo ai;
3000 if (ps.pkg != null) {
3001 ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
3002 ps.readUserState(userId), userId);
3003 } else {
3004 ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
3005 }
3006 if (ai != null) {
3007 list.add(ai);
3008 }
3009 }
3010 } else {
3011 list = new ArrayList<ApplicationInfo>(mPackages.size());
3012 for (PackageParser.Package p : mPackages.values()) {
3013 if (p.mExtras != null) {
3014 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
3015 ((PackageSetting)p.mExtras).readUserState(userId), userId);
3016 if (ai != null) {
3017 list.add(ai);
Dianne Hackborne7991752013-01-16 17:56:46 -08003018 }
3019 }
3020 }
3021 }
3022
Dianne Hackbornd8e1dbb2013-01-17 17:47:37 -08003023 return new ParceledListSlice<ApplicationInfo>(list);
Dianne Hackborne7991752013-01-16 17:56:46 -08003024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 }
3026
3027 public List<ApplicationInfo> getPersistentApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07003028 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029
Kenny Root447106f2011-03-23 11:00:15 -07003030 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003032 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003033 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003035 final PackageParser.Package p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 if (p.applicationInfo != null
3037 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07003038 && (!mSafeMode || isSystemApp(p))) {
Amith Yamasani13593602012-03-22 16:16:17 -07003039 PackageSetting ps = mSettings.mPackages.get(p.packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003040 if (ps != null) {
3041 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
3042 ps.readUserState(userId), userId);
3043 if (ai != null) {
3044 finalList.add(ai);
3045 }
3046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 }
3048 }
3049 }
3050
3051 return finalList;
3052 }
3053
Amith Yamasani483f3b02012-03-13 16:08:00 -07003054 @Override
3055 public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07003056 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07003057 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 synchronized (mPackages) {
3059 final PackageParser.Provider provider = mProviders.get(name);
Amith Yamasani13593602012-03-22 16:16:17 -07003060 PackageSetting ps = provider != null
3061 ? mSettings.mPackages.get(provider.owner.packageName)
3062 : null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003063 return ps != null
Amith Yamasani483f3b02012-03-13 16:08:00 -07003064 && mSettings.isEnabledLPr(provider.info, flags, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 && (!mSafeMode || (provider.info.applicationInfo.flags
3066 &ApplicationInfo.FLAG_SYSTEM) != 0)
Amith Yamasani13593602012-03-22 16:16:17 -07003067 ? PackageParser.generateProviderInfo(provider, flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003068 ps.readUserState(userId), userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 : null;
3070 }
3071 }
3072
Fred Quintana718d8a22009-04-29 17:53:20 -07003073 /**
3074 * @deprecated
3075 */
Kenny Root60f7ad82011-03-22 12:49:06 -07003076 @Deprecated
3077 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07003078 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003080 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
3081 .iterator();
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003082 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 while (i.hasNext()) {
3084 Map.Entry<String, PackageParser.Provider> entry = i.next();
3085 PackageParser.Provider p = entry.getValue();
Amith Yamasani13593602012-03-22 16:16:17 -07003086 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003088 if (ps != null && p.syncable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 && (!mSafeMode || (p.info.applicationInfo.flags
3090 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003091 ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
3092 ps.readUserState(userId), userId);
3093 if (info != null) {
3094 outNames.add(entry.getKey());
3095 outInfo.add(info);
3096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 }
3098 }
3099 }
3100 }
3101
3102 public List<ProviderInfo> queryContentProviders(String processName,
3103 int uid, int flags) {
3104 ArrayList<ProviderInfo> finalList = null;
3105
Kenny Root447106f2011-03-23 11:00:15 -07003106 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003108 final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
Amith Yamasani483f3b02012-03-13 16:08:00 -07003109 final int userId = processName != null ?
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003110 UserHandle.getUserId(uid) : UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003112 final PackageParser.Provider p = i.next();
Amith Yamasani13593602012-03-22 16:16:17 -07003113 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003114 if (ps != null && p.info.authority != null
Kenny Root447106f2011-03-23 11:00:15 -07003115 && (processName == null
3116 || (p.info.processName.equals(processName)
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003117 && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
Amith Yamasani483f3b02012-03-13 16:08:00 -07003118 && mSettings.isEnabledLPr(p.info, flags, userId)
Kenny Root447106f2011-03-23 11:00:15 -07003119 && (!mSafeMode
3120 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 if (finalList == null) {
3122 finalList = new ArrayList<ProviderInfo>(3);
3123 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003124 ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
3125 ps.readUserState(userId), userId);
Dianne Hackborn4428e172012-08-24 17:43:05 -07003126 if (info != null) {
3127 finalList.add(info);
3128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 }
3130 }
3131 }
3132
3133 if (finalList != null) {
3134 Collections.sort(finalList, mProviderInitOrderSorter);
3135 }
3136
3137 return finalList;
3138 }
3139
3140 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
3141 int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07003142 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 synchronized (mPackages) {
3144 final PackageParser.Instrumentation i = mInstrumentation.get(name);
3145 return PackageParser.generateInstrumentationInfo(i, flags);
3146 }
3147 }
3148
3149 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
3150 int flags) {
3151 ArrayList<InstrumentationInfo> finalList =
3152 new ArrayList<InstrumentationInfo>();
3153
Kenny Root447106f2011-03-23 11:00:15 -07003154 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003156 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003158 final PackageParser.Instrumentation p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 if (targetPackage == null
3160 || targetPackage.equals(p.info.targetPackage)) {
Dianne Hackborn4428e172012-08-24 17:43:05 -07003161 InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p,
3162 flags);
3163 if (ii != null) {
3164 finalList.add(ii);
3165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 }
3167 }
3168 }
3169
3170 return finalList;
3171 }
3172
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003173 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07003175 if (files == null) {
3176 Log.d(TAG, "No files in app dir " + dir);
3177 return;
3178 }
3179
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003180 if (DEBUG_PACKAGE_SCANNING) {
Joe Onorato431bb222010-10-18 19:13:23 -04003181 Log.d(TAG, "Scanning app dir " + dir);
3182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183
3184 int i;
3185 for (i=0; i<files.length; i++) {
3186 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003187 if (!isPackageFilename(files[i])) {
3188 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003189 continue;
3190 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003191 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003192 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003193 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003194 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
3195 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003196 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003197 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003198 file.delete();
3199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 }
3201 }
3202
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003203 private static File getSettingsProblemFile() {
3204 File dataDir = Environment.getDataDirectory();
3205 File systemDir = new File(dataDir, "system");
3206 File fname = new File(systemDir, "uiderrors.txt");
3207 return fname;
3208 }
3209
Kenny Rootcf0b38c2011-03-22 14:17:59 -07003210 static void reportSettingsProblem(int priority, String msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003212 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 FileOutputStream out = new FileOutputStream(fname, true);
3214 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003215 SimpleDateFormat formatter = new SimpleDateFormat();
3216 String dateString = formatter.format(new Date(System.currentTimeMillis()));
3217 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 pw.close();
3219 FileUtils.setPermissions(
3220 fname.toString(),
3221 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
3222 -1, -1);
3223 } catch (java.io.IOException e) {
3224 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003225 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 }
3227
3228 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
3229 PackageParser.Package pkg, File srcFile, int parseFlags) {
3230 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07003231 if (ps != null
3232 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07003233 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07003234 if (ps.signatures.mSignatures != null
3235 && ps.signatures.mSignatures.length != 0) {
3236 // Optimization: reuse the existing cached certificates
3237 // if the package appears to be unchanged.
3238 pkg.mSignatures = ps.signatures.mSignatures;
3239 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 }
Jeff Browne7600722010-04-07 18:28:23 -07003241
3242 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003243 } else {
Jeff Browne7600722010-04-07 18:28:23 -07003244 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
3245 }
3246
3247 if (!pp.collectCertificates(pkg, parseFlags)) {
3248 mLastScanError = pp.getParseError();
3249 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 }
3251 }
3252 return true;
3253 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 /*
3256 * Scan a package and return the newly parsed package.
3257 * Returns null in case of errors and the error code is stored in mLastScanError
3258 */
3259 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003260 int parseFlags, int scanMode, long currentTime, UserHandle user) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003262 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003264 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07003266 pp.setOnlyCoreApps(mOnlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003268 scanPath, mMetrics, parseFlags);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 if (pkg == null) {
3271 mLastScanError = pp.getParseError();
3272 return null;
3273 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003274
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003275 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003276 PackageSetting updatedPkg;
Kenny Root447106f2011-03-23 11:00:15 -07003277 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003279 // Look to see if we already know about this package.
3280 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003281 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003282 // This package has been renamed to its original name. Let's
3283 // use that.
Kenny Root447106f2011-03-23 11:00:15 -07003284 ps = mSettings.peekPackageLPr(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003285 }
3286 // If there was no original package, see one for the real package name.
3287 if (ps == null) {
Kenny Root447106f2011-03-23 11:00:15 -07003288 ps = mSettings.peekPackageLPr(pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003289 }
3290 // Check to see if this package could be hiding/updating a system
3291 // package. Must look for it either under the original or real
3292 // package name depending on our state.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003293 updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003295 // First check if this is a system package that may involve an update
3296 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07003297 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003298 // The path has changed from what was last scanned... check the
3299 // version of the new path against what we have stored to determine
3300 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003301 if (pkg.mVersionCode < ps.versionCode) {
3302 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003303 // Ignore entry. Skip it.
3304 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003305 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003306 + " better than this " + pkg.mVersionCode);
Dianne Hackbornc4d27a72013-01-22 18:30:17 -08003307 if (!updatedPkg.codePath.equals(scanFile)) {
3308 Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
3309 + ps.name + " changing from " + updatedPkg.codePathString
3310 + " to " + scanFile);
3311 updatedPkg.codePath = scanFile;
3312 updatedPkg.codePathString = scanFile.toString();
3313 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003314 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3315 return null;
3316 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003317 // The current app on the system partion is better than
3318 // what we have updated to on the data partition; switch
3319 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003320 // At this point, its safely assumed that package installation for
3321 // apps in system partition will go through. If not there won't be a working
3322 // version of the app
Kenny Root447106f2011-03-23 11:00:15 -07003323 // writer
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003324 synchronized (mPackages) {
3325 // Just remove the loaded entries from package lists.
3326 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003327 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003328 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003329 + "reverting from " + ps.codePathString
3330 + ": new version " + pkg.mVersionCode
3331 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003332
3333 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3334 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Dianne Hackborn4428e172012-08-24 17:43:05 -07003335 synchronized (mInstallLock) {
Kenny Root208d3412012-05-07 19:42:35 -07003336 args.cleanUpResourcesLI();
3337 }
3338 synchronized (mPackages) {
3339 mSettings.enableSystemPackageLPw(ps.name);
3340 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 }
3343 }
Kenny Root208d3412012-05-07 19:42:35 -07003344
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003345 if (updatedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07003346 // An updated system app will not have the PARSE_IS_SYSTEM flag set
3347 // initially
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003348 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
3349 }
3350 // Verify certificates against what was last scanned
3351 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003352 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003353 return null;
3354 }
Kenny Root208d3412012-05-07 19:42:35 -07003355
3356 /*
3357 * A new system app appeared, but we already had a non-system one of the
3358 * same name installed earlier.
3359 */
3360 boolean shouldHideSystemApp = false;
3361 if (updatedPkg == null && ps != null
3362 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
3363 /*
3364 * Check to make sure the signatures match first. If they don't,
3365 * wipe the installed application and its data.
3366 */
3367 if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
3368 != PackageManager.SIGNATURE_MATCH) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003369 deletePackageLI(pkg.packageName, null, true, 0, null, false);
Kenny Root208d3412012-05-07 19:42:35 -07003370 ps = null;
3371 } else {
3372 /*
3373 * If the newly-added system app is an older version than the
3374 * already installed version, hide it. It will be scanned later
3375 * and re-added like an update.
3376 */
3377 if (pkg.mVersionCode < ps.versionCode) {
3378 shouldHideSystemApp = true;
3379 } else {
3380 /*
3381 * The newly found system app is a newer version that the
3382 * one previously installed. Simply remove the
3383 * already-installed application and replace it with our own
3384 * while keeping the application data.
3385 */
3386 Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
3387 + ps.codePathString + ": new version " + pkg.mVersionCode
3388 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003389 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3390 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Dianne Hackborn4428e172012-08-24 17:43:05 -07003391 synchronized (mInstallLock) {
Kenny Root208d3412012-05-07 19:42:35 -07003392 args.cleanUpResourcesLI();
3393 }
3394 }
3395 }
3396 }
3397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 // The apk is forward locked (not public) if its code and resources
3399 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003400 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003402 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07003403 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003404
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003405 String codePath = null;
3406 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003407 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
3408 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003409 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003410 } else {
3411 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003412 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003413 }
3414 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003415 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003416 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003417
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003418 codePath = pkg.mScanPath;
3419 // Set application objects path explicitly.
3420 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 // Note that we invoke the following method only if we are about to unpack an application
Kenny Root208d3412012-05-07 19:42:35 -07003422 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003423 | SCAN_UPDATE_SIGNATURE, currentTime, user);
Kenny Root208d3412012-05-07 19:42:35 -07003424
3425 /*
3426 * If the system app should be overridden by a previously installed
3427 * data, hide the system app now and let the /data/app scan pick it up
3428 * again.
3429 */
3430 if (shouldHideSystemApp) {
3431 synchronized (mPackages) {
3432 /*
3433 * We have to grant systems permissions before we hide, because
3434 * grantPermissions will assume the package update is trying to
3435 * expand its permissions.
3436 */
3437 grantPermissionsLPw(pkg, true);
3438 mSettings.disableSystemPackageLPw(pkg.packageName);
3439 }
3440 }
3441
3442 return scannedPkg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 }
3444
Kenny Root85387d72010-08-26 10:13:11 -07003445 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
3446 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003447 pkg.mPath = pkg.mScanPath = destCodePath;
3448 pkg.applicationInfo.sourceDir = destCodePath;
3449 pkg.applicationInfo.publicSourceDir = destResPath;
3450 }
3451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 private static String fixProcessName(String defProcessName,
3453 String processName, int uid) {
3454 if (processName == null) {
3455 return defProcessName;
3456 }
3457 return processName;
3458 }
3459
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003460 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003461 PackageParser.Package pkg) {
3462 if (pkgSetting.signatures.mSignatures != null) {
3463 // Already existing package. Make sure signatures match
Kenny Root447106f2011-03-23 11:00:15 -07003464 if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003465 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003466 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003467 + " signatures do not match the previously installed version; ignoring!");
3468 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 return false;
3470 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003471 }
3472 // Check for shared user signatures
3473 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003474 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003475 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3476 Slog.e(TAG, "Package " + pkg.packageName
3477 + " has no signatures that match those in shared user "
3478 + pkgSetting.sharedUser.name + "; ignoring!");
3479 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
3480 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 }
3483 return true;
3484 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003485
Kenny Root461ff1f2011-08-09 09:43:03 -07003486 /**
3487 * Enforces that only the system UID or root's UID can call a method exposed
3488 * via Binder.
3489 *
3490 * @param message used as message if SecurityException is thrown
3491 * @throws SecurityException if the caller is not system or root
3492 */
3493 private static final void enforceSystemOrRoot(String message) {
3494 final int uid = Binder.getCallingUid();
3495 if (uid != Process.SYSTEM_UID && uid != 0) {
3496 throw new SecurityException(message);
3497 }
3498 }
3499
Dianne Hackborn661cd522011-08-22 00:26:20 -07003500 public void performBootDexOpt() {
3501 ArrayList<PackageParser.Package> pkgs = null;
3502 synchronized (mPackages) {
3503 if (mDeferredDexOpt.size() > 0) {
3504 pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt);
3505 mDeferredDexOpt.clear();
3506 }
3507 }
3508 if (pkgs != null) {
3509 for (int i=0; i<pkgs.size(); i++) {
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003510 if (!isFirstBoot()) {
3511 try {
3512 ActivityManagerNative.getDefault().showBootMessage(
3513 mContext.getResources().getString(
3514 com.android.internal.R.string.android_upgrading_apk,
3515 i+1, pkgs.size()), true);
3516 } catch (RemoteException e) {
3517 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003518 }
3519 PackageParser.Package p = pkgs.get(i);
3520 synchronized (mInstallLock) {
3521 if (!p.mDidDexOpt) {
3522 performDexOptLI(p, false, false);
3523 }
3524 }
3525 }
3526 }
3527 }
3528
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003529 public boolean performDexOpt(String packageName) {
Kenny Root461ff1f2011-08-09 09:43:03 -07003530 enforceSystemOrRoot("Only the system can request dexopt be performed");
3531
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003532 if (!mNoDexOpt) {
3533 return false;
3534 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003535
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003536 PackageParser.Package p;
3537 synchronized (mPackages) {
3538 p = mPackages.get(packageName);
3539 if (p == null || p.mDidDexOpt) {
3540 return false;
3541 }
3542 }
3543 synchronized (mInstallLock) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003544 return performDexOptLI(p, false, false) == DEX_OPT_PERFORMED;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003545 }
3546 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003547
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003548 static final int DEX_OPT_SKIPPED = 0;
3549 static final int DEX_OPT_PERFORMED = 1;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003550 static final int DEX_OPT_DEFERRED = 2;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003551 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003552
Dianne Hackborn661cd522011-08-22 00:26:20 -07003553 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003554 boolean performed = false;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003555 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003556 String path = pkg.mScanPath;
3557 int ret = 0;
3558 try {
3559 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003560 if (!forceDex && defer) {
3561 mDeferredDexOpt.add(pkg);
3562 return DEX_OPT_DEFERRED;
3563 } else {
3564 Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
Kenny Root6a9b2cb2012-09-17 14:02:39 -07003565 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
3566 ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));
Dianne Hackborn661cd522011-08-22 00:26:20 -07003567 pkg.mDidDexOpt = true;
3568 performed = true;
3569 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003570 }
3571 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003572 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003573 ret = -1;
3574 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07003575 Slog.w(TAG, "IOException reading apk: " + path, e);
3576 ret = -1;
3577 } catch (dalvik.system.StaleDexCacheError e) {
3578 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
3579 ret = -1;
3580 } catch (Exception e) {
3581 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003582 ret = -1;
3583 }
3584 if (ret < 0) {
3585 //error from installer
3586 return DEX_OPT_FAILED;
3587 }
3588 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003589
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003590 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
3591 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08003592
Kenny Root447106f2011-03-23 11:00:15 -07003593 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003594 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003595 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003596 + " to " + newPkg.packageName
3597 + ": old package not in system partition");
3598 return false;
3599 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003600 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003601 + " to " + newPkg.packageName
3602 + ": old package still exists");
3603 return false;
3604 }
3605 return true;
3606 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003607
Amith Yamasani0b285492011-04-14 17:35:23 -07003608 File getDataPathForUser(int userId) {
3609 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003610 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003611
3612 private File getDataPathForPackage(String packageName, int userId) {
Kenny Root9c8625e2011-07-25 09:42:22 -07003613 /*
3614 * Until we fully support multiple users, return the directory we
3615 * previously would have. The PackageManagerTests will need to be
3616 * revised when this is changed back..
3617 */
3618 if (userId == 0) {
3619 return new File(mAppDataDir, packageName);
3620 } else {
3621 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003622 + File.separator + packageName);
Kenny Root9c8625e2011-07-25 09:42:22 -07003623 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003624 }
3625
Nick Kralevich15069212013-01-09 15:54:56 -08003626 private int createDataDirsLI(String packageName, int uid) {
Dave Burke383fa182012-10-23 23:12:19 -07003627 int[] users = sUserManager.getUserIds();
Nick Kralevich15069212013-01-09 15:54:56 -08003628 int res = mInstaller.install(packageName, uid, uid);
Dave Burke383fa182012-10-23 23:12:19 -07003629 if (res < 0) {
3630 return res;
3631 }
3632 for (int user : users) {
3633 if (user != 0) {
3634 res = mInstaller.createUserData(packageName,
Nick Kralevich15069212013-01-09 15:54:56 -08003635 UserHandle.getUid(user, uid), user);
Dave Burke383fa182012-10-23 23:12:19 -07003636 if (res < 0) {
3637 return res;
3638 }
Dianne Hackborn4428e172012-08-24 17:43:05 -07003639 }
3640 }
Dave Burke383fa182012-10-23 23:12:19 -07003641 return res;
Dianne Hackborn4428e172012-08-24 17:43:05 -07003642 }
3643
3644 private int removeDataDirsLI(String packageName) {
3645 int[] users = sUserManager.getUserIds();
3646 int res = 0;
3647 for (int user : users) {
3648 int resInner = mInstaller.remove(packageName, user);
3649 if (resInner < 0) {
3650 res = resInner;
3651 }
3652 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07003653
3654 final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
3655 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
3656 if (!nativeLibraryFile.delete()) {
3657 Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
3658 }
3659
Dianne Hackborn4428e172012-08-24 17:43:05 -07003660 return res;
3661 }
3662
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003663 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003664 int parseFlags, int scanMode, long currentTime, UserHandle user) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003665 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08003666 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
3667 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003668 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003669 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003670 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
3671 return null;
3672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 mScanningPath = scanFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3676 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
3677 }
3678
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003679 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 synchronized (mPackages) {
3681 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003682 Slog.w(TAG, "*************************************************");
3683 Slog.w(TAG, "Core android package being redefined. Skipping.");
3684 Slog.w(TAG, " file=" + mScanningPath);
3685 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3687 return null;
3688 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 // Set up information for our fall-back user intent resolution
3691 // activity.
3692 mPlatformPackage = pkg;
3693 pkg.mVersionCode = mSdkVersion;
3694 mAndroidApplication = pkg.applicationInfo;
3695 mResolveActivity.applicationInfo = mAndroidApplication;
3696 mResolveActivity.name = ResolverActivity.class.getName();
3697 mResolveActivity.packageName = mAndroidApplication.packageName;
Dianne Hackborn8da429e2012-09-23 12:52:19 -07003698 mResolveActivity.processName = "system:ui";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3700 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08003701 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 mResolveActivity.exported = true;
3703 mResolveActivity.enabled = true;
3704 mResolveInfo.activityInfo = mResolveActivity;
3705 mResolveInfo.priority = 0;
3706 mResolveInfo.preferredOrder = 0;
3707 mResolveInfo.match = 0;
3708 mResolveComponentName = new ComponentName(
3709 mAndroidApplication.packageName, mResolveActivity.name);
3710 }
3711 }
3712
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003713 if (DEBUG_PACKAGE_SCANNING) {
3714 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3715 Log.d(TAG, "Scanning package " + pkg.packageName);
3716 }
3717
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003718 if (mPackages.containsKey(pkg.packageName)
3719 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003720 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3723 return null;
3724 }
3725
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003726 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003727 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
3728 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 SharedUserSetting suid = null;
3731 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003732
Kenny Root502e9a42011-01-10 13:48:15 -08003733 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003734 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08003735 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003736 pkg.mRealPackage = null;
3737 pkg.mAdoptPermissions = null;
3738 }
Kenny Root502e9a42011-01-10 13:48:15 -08003739
Kenny Root447106f2011-03-23 11:00:15 -07003740 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 synchronized (mPackages) {
3742 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07003743 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
3744 if (mTmpSharedLibraries == null ||
3745 mTmpSharedLibraries.length < mSharedLibraries.size()) {
3746 mTmpSharedLibraries = new String[mSharedLibraries.size()];
3747 }
3748 int num = 0;
3749 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
3750 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003751 final String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003753 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07003755 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
3757 return null;
3758 }
Dianne Hackborn49237342009-08-27 20:08:01 -07003759 mTmpSharedLibraries[num] = file;
3760 num++;
3761 }
3762 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
3763 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003764 final String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
Dianne Hackborn49237342009-08-27 20:08:01 -07003765 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003766 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07003767 + " desires unavailable shared library "
3768 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
3769 } else {
3770 mTmpSharedLibraries[num] = file;
3771 num++;
3772 }
3773 }
3774 if (num > 0) {
3775 pkg.usesLibraryFiles = new String[num];
3776 System.arraycopy(mTmpSharedLibraries, 0,
3777 pkg.usesLibraryFiles, 0, num);
3778 }
Kenny Root1683afa2011-01-07 14:27:50 -08003779 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 if (pkg.mSharedUserId != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003782 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 pkg.applicationInfo.flags, true);
3784 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003785 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003786 + " for shared user failed");
3787 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3788 return null;
3789 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003790 if (DEBUG_PACKAGE_SCANNING) {
3791 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3792 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
3793 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 }
3795 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003796
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003797 // Check if we are renaming from an original package name.
3798 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003799 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08003800 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003801 // This package may need to be renamed to a previously
3802 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07003803 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003804 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003805 // This package had originally been installed as the
3806 // original name, and we have already taken care of
3807 // transitioning to the new one. Just update the new
3808 // one to continue using the old name.
3809 realName = pkg.mRealPackage;
3810 if (!pkg.packageName.equals(renamed)) {
3811 // Callers into this function may have already taken
3812 // care of renaming the package; only do it here if
3813 // it is not already done.
3814 pkg.setPackageName(renamed);
3815 }
3816
Dianne Hackbornc1552392010-03-03 16:19:01 -08003817 } else {
3818 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07003819 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08003820 pkg.mOriginalPackages.get(i))) != null) {
3821 // We do have the package already installed under its
3822 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07003823 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08003824 // New package is not compatible with original.
3825 origPackage = null;
3826 continue;
3827 } else if (origPackage.sharedUser != null) {
3828 // Make sure uid is compatible between packages.
3829 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003830 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08003831 + " to " + pkg.packageName + ": old uid "
3832 + origPackage.sharedUser.name
3833 + " differs from " + pkg.mSharedUserId);
3834 origPackage = null;
3835 continue;
3836 }
3837 } else {
3838 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
3839 + pkg.packageName + " to old name " + origPackage.name);
3840 }
3841 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003842 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003843 }
3844 }
3845 }
3846
3847 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003848 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003849 + " was transferred to another, but its .apk remains");
3850 }
3851
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003852 // Just create the setting, don't add it yet. For already existing packages
3853 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07003854 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003855 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07003856 pkg.applicationInfo.flags, user, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003858 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3860 return null;
3861 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003862
3863 if (pkgSetting.origPackage != null) {
3864 // If we are first transitioning from an original package,
3865 // fix up the new package's name now. We need to do this after
3866 // looking up the package under its new name, so getPackageLP
3867 // can take care of fiddling things correctly.
3868 pkg.setPackageName(origPackage.name);
3869
3870 // File a report about this.
3871 String msg = "New package " + pkgSetting.realName
3872 + " renamed to replace old package " + pkgSetting.name;
3873 reportSettingsProblem(Log.WARN, msg);
3874
3875 // Make a note of it.
3876 mTransferedPackages.add(origPackage.name);
3877
3878 // No longer need to retain this.
3879 pkgSetting.origPackage = null;
3880 }
3881
3882 if (realName != null) {
3883 // Make a note of it.
3884 mTransferedPackages.add(pkg.packageName);
3885 }
3886
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003887 if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3889 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003890
Amith Yamasani13593602012-03-22 16:16:17 -07003891 pkg.applicationInfo.uid = pkgSetting.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003893
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003894 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003895 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 return null;
3897 }
3898 // The signature has changed, but this package is in the system
3899 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003900 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 // However... if this package is part of a shared user, but it
3902 // doesn't match the signature of the shared user, let's fail.
3903 // What this means is that you can't change the signatures
3904 // associated with an overall shared user, which doesn't seem all
3905 // that unreasonable.
3906 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003907 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003908 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3909 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3911 return null;
3912 }
3913 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003914 // File a report about this.
3915 String msg = "System package " + pkg.packageName
3916 + " signature changed; retaining data.";
3917 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003919
The Android Open Source Project10592532009-03-18 17:39:46 -07003920 // Verify that this new package doesn't have any content providers
3921 // that conflict with existing packages. Only do this if the
3922 // package isn't already installed, since we don't want to break
3923 // things that are installed.
3924 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08003925 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07003926 int i;
3927 for (i=0; i<N; i++) {
3928 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003929 if (p.info.authority != null) {
3930 String names[] = p.info.authority.split(";");
3931 for (int j = 0; j < names.length; j++) {
3932 if (mProviders.containsKey(names[j])) {
3933 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003934 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003935 " (in package " + pkg.applicationInfo.packageName +
3936 ") is already used by "
3937 + ((other != null && other.getComponentName() != null)
3938 ? other.getComponentName().getPackageName() : "?"));
3939 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3940 return null;
3941 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003942 }
3943 }
3944 }
3945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946
Kenny Root447106f2011-03-23 11:00:15 -07003947 if (pkg.mAdoptPermissions != null) {
3948 // This package wants to adopt ownership of permissions from
3949 // another package.
3950 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
3951 final String origName = pkg.mAdoptPermissions.get(i);
3952 final PackageSetting orig = mSettings.peekPackageLPr(origName);
3953 if (orig != null) {
3954 if (verifyPackageUpdateLPr(orig, pkg)) {
3955 Slog.i(TAG, "Adopting permissions from " + origName + " to "
3956 + pkg.packageName);
3957 mSettings.transferPermissionsLPw(origName, pkg.packageName);
3958 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003959 }
3960 }
3961 }
3962 }
Kenny Root447106f2011-03-23 11:00:15 -07003963
3964 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003965
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003966 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 pkg.applicationInfo.processName = fixProcessName(
3969 pkg.applicationInfo.packageName,
3970 pkg.applicationInfo.processName,
3971 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972
3973 File dataPath;
3974 if (mPlatformPackage == pkg) {
3975 // The system package is special.
3976 dataPath = new File (Environment.getDataDirectory(), "system");
3977 pkg.applicationInfo.dataDir = dataPath.getPath();
3978 } else {
3979 // This is a normal package, need to make its data directory.
Dave Burke383fa182012-10-23 23:12:19 -07003980 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003981
Dave Burke383fa182012-10-23 23:12:19 -07003982 boolean uidError = false;
3983
3984 if (dataPath.exists()) {
3985 int currentUid = 0;
3986 try {
3987 StructStat stat = Libcore.os.stat(dataPath.getPath());
3988 currentUid = stat.st_uid;
3989 } catch (ErrnoException e) {
3990 Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003992
Dave Burke383fa182012-10-23 23:12:19 -07003993 // If we have mismatched owners for the data path, we have a problem.
3994 if (currentUid != pkg.applicationInfo.uid) {
3995 boolean recovered = false;
3996 if (currentUid == 0) {
3997 // The directory somehow became owned by root. Wow.
3998 // This is probably because the system was stopped while
3999 // installd was in the middle of messing with its libs
4000 // directory. Ask installd to fix that.
4001 int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
4002 pkg.applicationInfo.uid);
4003 if (ret >= 0) {
4004 recovered = true;
4005 String msg = "Package " + pkg.packageName
4006 + " unexpectedly changed to uid 0; recovered to " +
4007 + pkg.applicationInfo.uid;
4008 reportSettingsProblem(Log.WARN, msg);
4009 }
4010 }
4011 if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
4012 || (scanMode&SCAN_BOOTING) != 0)) {
4013 // If this is a system app, we can at least delete its
4014 // current data so the application will still work.
4015 int ret = removeDataDirsLI(pkgName);
4016 if (ret >= 0) {
4017 // TODO: Kill the processes first
4018 // Old data gone!
4019 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
4020 ? "System package " : "Third party package ";
4021 String msg = prefix + pkg.packageName
4022 + " has changed from uid: "
4023 + currentUid + " to "
4024 + pkg.applicationInfo.uid + "; old data erased";
4025 reportSettingsProblem(Log.WARN, msg);
4026 recovered = true;
4027
4028 // And now re-install the app.
Nick Kralevich15069212013-01-09 15:54:56 -08004029 ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
Dave Burke383fa182012-10-23 23:12:19 -07004030 if (ret == -1) {
4031 // Ack should not happen!
4032 msg = prefix + pkg.packageName
4033 + " could not have data directory re-created after delete.";
4034 reportSettingsProblem(Log.WARN, msg);
4035 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4036 return null;
4037 }
4038 }
4039 if (!recovered) {
4040 mHasSystemUidErrors = true;
4041 }
4042 } else if (!recovered) {
4043 // If we allow this install to proceed, we will be broken.
4044 // Abort, abort!
4045 mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED;
4046 return null;
4047 }
4048 if (!recovered) {
4049 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
4050 + pkg.applicationInfo.uid + "/fs_"
4051 + currentUid;
4052 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
4053 String msg = "Package " + pkg.packageName
4054 + " has mismatched uid: "
4055 + currentUid + " on disk, "
4056 + pkg.applicationInfo.uid + " in settings";
4057 // writer
4058 synchronized (mPackages) {
4059 mSettings.mReadMessages.append(msg);
4060 mSettings.mReadMessages.append('\n');
4061 uidError = true;
4062 if (!pkgSetting.uidError) {
4063 reportSettingsProblem(Log.ERROR, msg);
4064 }
4065 }
4066 }
4067 }
Kenny Root4525f5b2012-10-22 14:24:23 -07004068 pkg.applicationInfo.dataDir = dataPath.getPath();
Dave Burke383fa182012-10-23 23:12:19 -07004069 } else {
4070 if (DEBUG_PACKAGE_SCANNING) {
4071 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4072 Log.v(TAG, "Want this data dir: " + dataPath);
4073 }
Nick Kralevich15069212013-01-09 15:54:56 -08004074 //invoke installer to do the actual installation
4075 int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
Dave Burke383fa182012-10-23 23:12:19 -07004076 if (ret < 0) {
4077 // Error from installer
4078 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4079 return null;
4080 }
4081
4082 if (dataPath.exists()) {
4083 pkg.applicationInfo.dataDir = dataPath.getPath();
4084 } else {
4085 Slog.w(TAG, "Unable to create data directory: " + dataPath);
4086 pkg.applicationInfo.dataDir = null;
4087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 }
Kenny Root85387d72010-08-26 10:13:11 -07004089
4090 /*
Dave Burke383fa182012-10-23 23:12:19 -07004091 * Set the data dir to the default "/data/data/<package name>/lib"
4092 * if we got here without anyone telling us different (e.g., apps
4093 * stored on SD card have their native libraries stored in the ASEC
4094 * container with the APK).
4095 *
4096 * This happens during an upgrade from a package settings file that
4097 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07004098 */
Dave Burke383fa182012-10-23 23:12:19 -07004099 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
Kenny Rootbd135c12010-10-05 12:26:27 -07004100 if (pkgSetting.nativeLibraryPathString == null) {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004101 setInternalAppNativeLibraryPath(pkg, pkgSetting);
Kenny Rootbd135c12010-10-05 12:26:27 -07004102 } else {
4103 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
4104 }
Kenny Root85387d72010-08-26 10:13:11 -07004105 }
Dave Burke383fa182012-10-23 23:12:19 -07004106
4107 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 }
4109
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004110 String path = scanFile.getPath();
4111 /* Note: We don't want to unpack the native binaries for
4112 * system applications, unless they have been updated
4113 * (the binaries are already under /system/lib).
4114 * Also, don't unpack libs for apps on the external card
4115 * since they should have their libraries in the ASEC
4116 * container already.
4117 *
4118 * In other words, we're going to unpack the binaries
4119 * only for non-system apps and system app upgrades.
4120 */
4121 if (pkg.applicationInfo.nativeLibraryDir != null) {
4122 try {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004123 File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
Kenny Root5832ead2011-08-02 15:47:08 -07004124 final String dataPathString = dataPath.getCanonicalPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07004125
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004126 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
4127 /*
4128 * Upgrading from a previous version of the OS sometimes
4129 * leaves native libraries in the /data/data/<app>/lib
4130 * directory for system apps even when they shouldn't be.
4131 * Recent changes in the JNI library search path
4132 * necessitates we remove those to match previous behavior.
4133 */
4134 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
4135 Log.i(TAG, "removed obsolete native libraries for system package "
4136 + path);
Kenny Root831baa22010-10-05 12:29:25 -07004137 }
Kenny Roota3e90792012-10-18 10:58:36 -07004138 } else {
4139 if (!isForwardLocked(pkg) && !isExternal(pkg)) {
4140 /*
4141 * Update native library dir if it starts with
4142 * /data/data
4143 */
4144 if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
4145 setInternalAppNativeLibraryPath(pkg, pkgSetting);
4146 nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
4147 }
Kenny Root66269ea2011-07-12 14:14:01 -07004148
Kenny Roota3e90792012-10-18 10:58:36 -07004149 try {
4150 if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
4151 Slog.e(TAG, "Unable to copy native libraries");
4152 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4153 return null;
4154 }
4155 } catch (IOException e) {
4156 Slog.e(TAG, "Unable to copy native libraries", e);
Kenny Rootddbe50d2012-09-06 13:18:37 -07004157 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4158 return null;
4159 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07004160 }
4161
Dianne Hackborn40e9f292012-11-27 19:12:23 -08004162 if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
Kenny Roota3e90792012-10-18 10:58:36 -07004163 final int[] userIds = sUserManager.getUserIds();
4164 synchronized (mInstallLock) {
4165 for (int userId : userIds) {
4166 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
4167 pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
4168 Slog.w(TAG, "Failed linking native library dir (user=" + userId
4169 + ")");
4170 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4171 return null;
4172 }
4173 }
Nick Kralevich7de350a2012-09-07 15:48:11 -07004174 }
Kenny Root831baa22010-10-05 12:29:25 -07004175 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004176 } catch (IOException ioe) {
Kenny Rootddbe50d2012-09-06 13:18:37 -07004177 Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004179 }
4180 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004181
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004182 if ((scanMode&SCAN_NO_DEX) == 0) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07004183 if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0)
4184 == DEX_OPT_FAILED) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07004185 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
4186 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 }
4188 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 if (mFactoryTest && pkg.requestedPermissions.contains(
4191 android.Manifest.permission.FACTORY_TEST)) {
4192 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
4193 }
4194
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004195 // Request the ActivityManager to kill the process(only for existing packages)
4196 // so that we do not end up in a confused state while the user is still using the older
4197 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004198 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004199 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004200 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004201 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004202
Kenny Root447106f2011-03-23 11:00:15 -07004203 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004205 // We don't expect installation to fail beyond this point,
4206 if ((scanMode&SCAN_MONITOR) != 0) {
4207 mAppDirs.put(pkg.mPath, pkg);
4208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07004210 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004211 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004212 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004213 // Make sure we don't accidentally delete its data.
Jeff Sharkey752cd922012-09-23 16:25:12 -07004214 final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
4215 while (iter.hasNext()) {
4216 PackageCleanItem item = iter.next();
4217 if (pkgName.equals(item.packageName)) {
4218 iter.remove();
4219 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004220 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07004221
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004222 // Take care of first install / last update times.
4223 if (currentTime != 0) {
4224 if (pkgSetting.firstInstallTime == 0) {
4225 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
4226 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
4227 pkgSetting.lastUpdateTime = currentTime;
4228 }
4229 } else if (pkgSetting.firstInstallTime == 0) {
4230 // We need *something*. Take time time stamp of the file.
4231 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
4232 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
4233 if (scanFileTime != pkgSetting.timeStamp) {
4234 // A package on the system image has changed; consider this
4235 // to be an update.
4236 pkgSetting.lastUpdateTime = scanFileTime;
4237 }
4238 }
4239
Geremy Condraf1bcca82013-01-07 22:35:24 -08004240 // Add the package's KeySets to the global KeySetManager
4241 KeySetManager ksm = mSettings.mKeySetManager;
4242 try {
4243 ksm.addSigningKeySetToPackage(pkg.packageName, pkg.mSigningKeys);
4244 if (pkg.mKeySetMapping != null) {
4245 for (Map.Entry<String, Set<PublicKey>> entry : pkg.mKeySetMapping.entrySet()) {
4246 if (entry.getValue() != null) {
4247 ksm.addDefinedKeySetToPackage(pkg.packageName,
4248 entry.getValue(), entry.getKey());
4249 }
4250 }
4251 }
4252 } catch (NullPointerException e) {
4253 Slog.e(TAG, "Could not add KeySet to " + pkg.packageName, e);
4254 } catch (IllegalArgumentException e) {
4255 Slog.e(TAG, "Could not add KeySet to malformed package" + pkg.packageName, e);
4256 }
4257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 int N = pkg.providers.size();
4259 StringBuilder r = null;
4260 int i;
4261 for (i=0; i<N; i++) {
4262 PackageParser.Provider p = pkg.providers.get(i);
4263 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
4264 p.info.processName, pkg.applicationInfo.uid);
4265 mProvidersByComponent.put(new ComponentName(p.info.packageName,
4266 p.info.name), p);
4267 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004268 if (p.info.authority != null) {
4269 String names[] = p.info.authority.split(";");
4270 p.info.authority = null;
4271 for (int j = 0; j < names.length; j++) {
4272 if (j == 1 && p.syncable) {
4273 // We only want the first authority for a provider to possibly be
4274 // syncable, so if we already added this provider using a different
4275 // authority clear the syncable flag. We copy the provider before
4276 // changing it because the mProviders object contains a reference
4277 // to a provider that we don't want to change.
4278 // Only do this for the second authority since the resulting provider
4279 // object can be the same for all future authorities for this provider.
4280 p = new PackageParser.Provider(p);
4281 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004283 if (!mProviders.containsKey(names[j])) {
4284 mProviders.put(names[j], p);
4285 if (p.info.authority == null) {
4286 p.info.authority = names[j];
4287 } else {
4288 p.info.authority = p.info.authority + ";" + names[j];
4289 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004290 if (DEBUG_PACKAGE_SCANNING) {
4291 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4292 Log.d(TAG, "Registered content provider: " + names[j]
4293 + ", className = " + p.info.name + ", isSyncable = "
4294 + p.info.isSyncable);
4295 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004296 } else {
4297 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004298 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004299 " (in package " + pkg.applicationInfo.packageName +
4300 "): name already used by "
4301 + ((other != null && other.getComponentName() != null)
4302 ? other.getComponentName().getPackageName() : "?"));
4303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305 }
4306 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4307 if (r == null) {
4308 r = new StringBuilder(256);
4309 } else {
4310 r.append(' ');
4311 }
4312 r.append(p.info.name);
4313 }
4314 }
4315 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004316 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 N = pkg.services.size();
4320 r = null;
4321 for (i=0; i<N; i++) {
4322 PackageParser.Service s = pkg.services.get(i);
4323 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
4324 s.info.processName, pkg.applicationInfo.uid);
4325 mServices.addService(s);
4326 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4327 if (r == null) {
4328 r = new StringBuilder(256);
4329 } else {
4330 r.append(' ');
4331 }
4332 r.append(s.info.name);
4333 }
4334 }
4335 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004336 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 N = pkg.receivers.size();
4340 r = null;
4341 for (i=0; i<N; i++) {
4342 PackageParser.Activity a = pkg.receivers.get(i);
4343 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4344 a.info.processName, pkg.applicationInfo.uid);
4345 mReceivers.addActivity(a, "receiver");
4346 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4347 if (r == null) {
4348 r = new StringBuilder(256);
4349 } else {
4350 r.append(' ');
4351 }
4352 r.append(a.info.name);
4353 }
4354 }
4355 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004356 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 N = pkg.activities.size();
4360 r = null;
4361 for (i=0; i<N; i++) {
4362 PackageParser.Activity a = pkg.activities.get(i);
4363 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4364 a.info.processName, pkg.applicationInfo.uid);
4365 mActivities.addActivity(a, "activity");
4366 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4367 if (r == null) {
4368 r = new StringBuilder(256);
4369 } else {
4370 r.append(' ');
4371 }
4372 r.append(a.info.name);
4373 }
4374 }
4375 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004376 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004379 N = pkg.permissionGroups.size();
4380 r = null;
4381 for (i=0; i<N; i++) {
4382 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
4383 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
4384 if (cur == null) {
4385 mPermissionGroups.put(pg.info.name, pg);
4386 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4387 if (r == null) {
4388 r = new StringBuilder(256);
4389 } else {
4390 r.append(' ');
4391 }
4392 r.append(pg.info.name);
4393 }
4394 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004395 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 + pg.info.packageName + " ignored: original from "
4397 + cur.info.packageName);
4398 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4399 if (r == null) {
4400 r = new StringBuilder(256);
4401 } else {
4402 r.append(' ');
4403 }
4404 r.append("DUP:");
4405 r.append(pg.info.name);
4406 }
4407 }
4408 }
4409 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004410 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 N = pkg.permissions.size();
4414 r = null;
4415 for (i=0; i<N; i++) {
4416 PackageParser.Permission p = pkg.permissions.get(i);
4417 HashMap<String, BasePermission> permissionMap =
4418 p.tree ? mSettings.mPermissionTrees
4419 : mSettings.mPermissions;
4420 p.group = mPermissionGroups.get(p.info.group);
4421 if (p.info.group == null || p.group != null) {
4422 BasePermission bp = permissionMap.get(p.info.name);
4423 if (bp == null) {
4424 bp = new BasePermission(p.info.name, p.info.packageName,
4425 BasePermission.TYPE_NORMAL);
4426 permissionMap.put(p.info.name, bp);
4427 }
4428 if (bp.perm == null) {
4429 if (bp.sourcePackage == null
4430 || bp.sourcePackage.equals(p.info.packageName)) {
4431 BasePermission tree = findPermissionTreeLP(p.info.name);
4432 if (tree == null
4433 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004434 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 bp.perm = p;
4436 bp.uid = pkg.applicationInfo.uid;
4437 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4438 if (r == null) {
4439 r = new StringBuilder(256);
4440 } else {
4441 r.append(' ');
4442 }
4443 r.append(p.info.name);
4444 }
4445 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004446 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 + p.info.packageName + " ignored: base tree "
4448 + tree.name + " is from package "
4449 + tree.sourcePackage);
4450 }
4451 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004452 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 + p.info.packageName + " ignored: original from "
4454 + bp.sourcePackage);
4455 }
4456 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4457 if (r == null) {
4458 r = new StringBuilder(256);
4459 } else {
4460 r.append(' ');
4461 }
4462 r.append("DUP:");
4463 r.append(p.info.name);
4464 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004465 if (bp.perm == p) {
4466 bp.protectionLevel = p.info.protectionLevel;
4467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004469 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 + p.info.packageName + " ignored: no group "
4471 + p.group);
4472 }
4473 }
4474 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004475 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 N = pkg.instrumentation.size();
4479 r = null;
4480 for (i=0; i<N; i++) {
4481 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
4482 a.info.packageName = pkg.applicationInfo.packageName;
4483 a.info.sourceDir = pkg.applicationInfo.sourceDir;
4484 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
4485 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07004486 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004487 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4489 if (r == null) {
4490 r = new StringBuilder(256);
4491 } else {
4492 r.append(' ');
4493 }
4494 r.append(a.info.name);
4495 }
4496 }
4497 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004498 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004500
Dianne Hackborn854060af2009-07-09 18:14:31 -07004501 if (pkg.protectedBroadcasts != null) {
4502 N = pkg.protectedBroadcasts.size();
4503 for (i=0; i<N; i++) {
4504 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
4505 }
4506 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 pkgSetting.setTimeStamp(scanFileTime);
4509 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 return pkg;
4512 }
4513
Kenny Rootddbe50d2012-09-06 13:18:37 -07004514 private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
4515 PackageSetting pkgSetting) {
4516 final String apkLibPath = getApkName(pkgSetting.codePathString);
4517 final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
4518 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
4519 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
4520 }
4521
4522 private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
4523 throws IOException {
4524 if (!nativeLibraryDir.isDirectory()) {
4525 nativeLibraryDir.delete();
Kenny Root9bbd70a2012-09-10 11:13:36 -07004526
Kenny Rootddbe50d2012-09-06 13:18:37 -07004527 if (!nativeLibraryDir.mkdir()) {
4528 throw new IOException("Cannot create " + nativeLibraryDir.getPath());
4529 }
Kenny Root9bbd70a2012-09-10 11:13:36 -07004530
Kenny Rootddbe50d2012-09-06 13:18:37 -07004531 try {
4532 Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
4533 | S_IXOTH);
4534 } catch (ErrnoException e) {
4535 throw new IOException("Cannot chmod native library directory "
4536 + nativeLibraryDir.getPath(), e);
4537 }
Kenny Root9bbd70a2012-09-10 11:13:36 -07004538 } else if (!SELinux.restorecon(nativeLibraryDir)) {
4539 throw new IOException("Cannot set SELinux context for " + nativeLibraryDir.getPath());
Kenny Rootddbe50d2012-09-06 13:18:37 -07004540 }
4541
4542 /*
4543 * If this is an internal application or our nativeLibraryPath points to
4544 * the app-lib directory, unpack the libraries if necessary.
4545 */
4546 return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
4547 }
4548
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004549 private void killApplication(String pkgName, int appId) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004550 // Request the ActivityManager to kill the process(only for existing packages)
4551 // so that we do not end up in a confused state while the user is still using the older
4552 // version of the application while the new one gets installed.
4553 IActivityManager am = ActivityManagerNative.getDefault();
4554 if (am != null) {
4555 try {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004556 am.killApplicationWithAppId(pkgName, appId);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004557 } catch (RemoteException e) {
4558 }
4559 }
4560 }
4561
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004562 void removePackageLI(PackageSetting ps, boolean chatty) {
4563 if (DEBUG_INSTALL) {
4564 if (chatty)
4565 Log.d(TAG, "Removing package " + ps.name);
4566 }
4567
4568 // writer
4569 synchronized (mPackages) {
4570 mPackages.remove(ps.name);
4571 if (ps.codePathString != null) {
4572 mAppDirs.remove(ps.codePathString);
4573 }
4574
4575 final PackageParser.Package pkg = ps.pkg;
4576 if (pkg != null) {
4577 cleanPackageDataStructuresLILPw(pkg, chatty);
4578 }
4579 }
4580 }
4581
4582 void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004583 if (DEBUG_INSTALL) {
4584 if (chatty)
4585 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
4586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587
Kenny Root447106f2011-03-23 11:00:15 -07004588 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 mPackages.remove(pkg.applicationInfo.packageName);
4591 if (pkg.mPath != null) {
4592 mAppDirs.remove(pkg.mPath);
4593 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004594 cleanPackageDataStructuresLILPw(pkg, chatty);
4595 }
4596 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004597
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004598 void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
4599 int N = pkg.providers.size();
4600 StringBuilder r = null;
4601 int i;
4602 for (i=0; i<N; i++) {
4603 PackageParser.Provider p = pkg.providers.get(i);
4604 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
4605 p.info.name));
4606 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004607
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004608 /* There was another ContentProvider with this authority when
4609 * this app was installed so this authority is null,
4610 * Ignore it as we don't have to unregister the provider.
4611 */
4612 continue;
4613 }
4614 String names[] = p.info.authority.split(";");
4615 for (int j = 0; j < names.length; j++) {
4616 if (mProviders.get(names[j]) == p) {
4617 mProviders.remove(names[j]);
4618 if (DEBUG_REMOVE) {
4619 if (chatty)
4620 Log.d(TAG, "Unregistered content provider: " + names[j]
4621 + ", className = " + p.info.name + ", isSyncable = "
4622 + p.info.isSyncable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 }
4624 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004625 }
4626 if (chatty) {
4627 if (r == null) {
4628 r = new StringBuilder(256);
4629 } else {
4630 r.append(' ');
4631 }
4632 r.append(p.info.name);
4633 }
4634 }
4635 if (r != null) {
4636 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
4637 }
4638
4639 N = pkg.services.size();
4640 r = null;
4641 for (i=0; i<N; i++) {
4642 PackageParser.Service s = pkg.services.get(i);
4643 mServices.removeService(s);
4644 if (chatty) {
4645 if (r == null) {
4646 r = new StringBuilder(256);
4647 } else {
4648 r.append(' ');
4649 }
4650 r.append(s.info.name);
4651 }
4652 }
4653 if (r != null) {
4654 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
4655 }
4656
4657 N = pkg.receivers.size();
4658 r = null;
4659 for (i=0; i<N; i++) {
4660 PackageParser.Activity a = pkg.receivers.get(i);
4661 mReceivers.removeActivity(a, "receiver");
4662 if (chatty) {
4663 if (r == null) {
4664 r = new StringBuilder(256);
4665 } else {
4666 r.append(' ');
4667 }
4668 r.append(a.info.name);
4669 }
4670 }
4671 if (r != null) {
4672 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
4673 }
4674
4675 N = pkg.activities.size();
4676 r = null;
4677 for (i=0; i<N; i++) {
4678 PackageParser.Activity a = pkg.activities.get(i);
4679 mActivities.removeActivity(a, "activity");
4680 if (chatty) {
4681 if (r == null) {
4682 r = new StringBuilder(256);
4683 } else {
4684 r.append(' ');
4685 }
4686 r.append(a.info.name);
4687 }
4688 }
4689 if (r != null) {
4690 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
4691 }
4692
4693 N = pkg.permissions.size();
4694 r = null;
4695 for (i=0; i<N; i++) {
4696 PackageParser.Permission p = pkg.permissions.get(i);
4697 BasePermission bp = mSettings.mPermissions.get(p.info.name);
4698 if (bp == null) {
4699 bp = mSettings.mPermissionTrees.get(p.info.name);
4700 }
4701 if (bp != null && bp.perm == p) {
4702 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 if (chatty) {
4704 if (r == null) {
4705 r = new StringBuilder(256);
4706 } else {
4707 r.append(' ');
4708 }
4709 r.append(p.info.name);
4710 }
4711 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004712 }
4713 if (r != null) {
4714 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
4715 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004716
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004717 N = pkg.instrumentation.size();
4718 r = null;
4719 for (i=0; i<N; i++) {
4720 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
4721 mInstrumentation.remove(a.getComponentName());
4722 if (chatty) {
4723 if (r == null) {
4724 r = new StringBuilder(256);
4725 } else {
4726 r.append(' ');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004728 r.append(a.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07004730 }
4731 if (r != null) {
4732 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 }
4734 }
4735
4736 private static final boolean isPackageFilename(String name) {
4737 return name != null && name.endsWith(".apk");
4738 }
4739
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004740 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
4741 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
4742 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
4743 return true;
4744 }
4745 }
4746 return false;
4747 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004748
4749 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
4750 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
4751 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
4752
Kenny Root447106f2011-03-23 11:00:15 -07004753 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborne639da72012-02-21 15:11:13 -08004754 PackageParser.Package pkgInfo, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07004756 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004758 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004759 if (bp.packageSetting == null) {
4760 // We may not yet have parsed the package, so just see if
4761 // we still know about its settings.
4762 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4763 }
4764 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004765 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004766 + " from package " + bp.sourcePackage);
4767 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004768 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4769 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4770 Slog.i(TAG, "Removing old permission tree: " + bp.name
4771 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004772 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004773 it.remove();
4774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 }
4776 }
4777
4778 // Make sure all dynamic permissions have been assigned to a package,
4779 // and make sure there are no dangling permissions.
4780 it = mSettings.mPermissions.values().iterator();
4781 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004782 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 if (bp.type == BasePermission.TYPE_DYNAMIC) {
4784 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
4785 + bp.name + " pkg=" + bp.sourcePackage
4786 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004787 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004788 final BasePermission tree = findPermissionTreeLP(bp.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07004789 if (tree != null && tree.perm != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004790 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 bp.perm = new PackageParser.Permission(tree.perm.owner,
4792 new PermissionInfo(bp.pendingInfo));
4793 bp.perm.info.packageName = tree.perm.info.packageName;
4794 bp.perm.info.name = bp.name;
4795 bp.uid = tree.uid;
4796 }
4797 }
4798 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004799 if (bp.packageSetting == null) {
4800 // We may not yet have parsed the package, so just see if
4801 // we still know about its settings.
4802 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4803 }
4804 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004805 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 + " from package " + bp.sourcePackage);
4807 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004808 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4809 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4810 Slog.i(TAG, "Removing old permission: " + bp.name
4811 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004812 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004813 it.remove();
4814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 }
4816 }
4817
4818 // Now update the permissions for all packages, in particular
4819 // replace the granted permissions of the system packages.
Dianne Hackborne639da72012-02-21 15:11:13 -08004820 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004821 for (PackageParser.Package pkg : mPackages.values()) {
4822 if (pkg != pkgInfo) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004823 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004824 }
4825 }
4826 }
4827
4828 if (pkgInfo != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004829 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 }
4831 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004832
Kenny Root447106f2011-03-23 11:00:15 -07004833 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
4834 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 if (ps == null) {
4836 return;
4837 }
4838 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08004839 HashSet<String> origPermissions = gp.grantedPermissions;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004840 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004842 if (replace) {
4843 ps.permissionsFixed = false;
4844 if (gp == ps) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004845 origPermissions = new HashSet<String>(gp.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004846 gp.grantedPermissions.clear();
4847 gp.gids = mGlobalGids;
4848 }
4849 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 if (gp.gids == null) {
4852 gp.gids = mGlobalGids;
4853 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 final int N = pkg.requestedPermissions.size();
4856 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07004857 final String name = pkg.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -08004858 //final boolean required = pkg.requestedPermssionsRequired.get(i);
Kenny Root447106f2011-03-23 11:00:15 -07004859 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004860 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004862 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 }
4864 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004865 if (bp != null && bp.packageSetting != null) {
4866 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004868 boolean allowedSig = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004869 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
4870 if (level == PermissionInfo.PROTECTION_NORMAL
4871 || level == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07004873 } else if (bp.packageSetting == null) {
4874 // This permission is invalid; skip it.
4875 allowed = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004876 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
Kenny Root447106f2011-03-23 11:00:15 -07004877 allowed = (compareSignatures(
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004878 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 == PackageManager.SIGNATURE_MATCH)
Kenny Root447106f2011-03-23 11:00:15 -07004880 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborne639da72012-02-21 15:11:13 -08004882 if (!allowed && (bp.protectionLevel
4883 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
Kenny Root85387d72010-08-26 10:13:11 -07004884 if (isSystemApp(pkg)) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004885 // For updated system applications, a system permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07004887 if (isUpdatedSystemApp(pkg)) {
Kenny Root447106f2011-03-23 11:00:15 -07004888 final PackageSetting sysPs = mSettings
4889 .getDisabledSystemPkgLPr(pkg.packageName);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004890 final GrantedPermissions origGp = sysPs.sharedUser != null
4891 ? sysPs.sharedUser : sysPs;
4892 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 allowed = true;
4894 } else {
4895 allowed = false;
4896 }
4897 } else {
4898 allowed = true;
4899 }
4900 }
4901 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004902 if (!allowed && (bp.protectionLevel
4903 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
4904 // For development permissions, a development permission
4905 // is granted only if it was already granted.
4906 if (origPermissions.contains(perm)) {
4907 allowed = true;
4908 } else {
4909 allowed = false;
4910 }
4911 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004912 if (allowed) {
4913 allowedSig = true;
4914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 } else {
4916 allowed = false;
4917 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004918 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 if (gp != ps) {
4920 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
4921 }
4922 }
4923 if (allowed) {
4924 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
4925 && ps.permissionsFixed) {
4926 // If this is an existing, non-system package, then
4927 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07004928 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07004930 // Except... if this is a permission that was added
4931 // to the platform (note: need to only do this when
4932 // updating the platform).
4933 final int NP = PackageParser.NEW_PERMISSIONS.length;
4934 for (int ip=0; ip<NP; ip++) {
4935 final PackageParser.NewPermissionInfo npi
4936 = PackageParser.NEW_PERMISSIONS[ip];
4937 if (npi.name.equals(perm)
4938 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
4939 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07004940 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07004941 + pkg.packageName);
4942 break;
4943 }
4944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 }
4946 }
4947 if (allowed) {
4948 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004949 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 gp.grantedPermissions.add(perm);
4951 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004952 } else if (!ps.haveGids) {
4953 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 }
4955 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004956 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 + " to package " + pkg.packageName
4958 + " because it was previously installed without");
4959 }
4960 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004961 if (gp.grantedPermissions.remove(perm)) {
4962 changedPermission = true;
4963 gp.gids = removeInts(gp.gids, bp.gids);
4964 Slog.i(TAG, "Un-granting permission " + perm
4965 + " from package " + pkg.packageName
4966 + " (protectionLevel=" + bp.protectionLevel
4967 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4968 + ")");
4969 } else {
4970 Slog.w(TAG, "Not granting permission " + perm
4971 + " to package " + pkg.packageName
4972 + " (protectionLevel=" + bp.protectionLevel
4973 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4974 + ")");
4975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 }
4977 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004978 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 + " in package " + pkg.packageName);
4980 }
4981 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004982
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004983 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004984 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4985 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 // This is the first that we have heard about this package, so the
4987 // permissions we have now selected are fixed until explicitly
4988 // changed.
4989 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004991 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004993
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08004994 final class ActivityIntentResolver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004996 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004997 boolean defaultOnly, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004998 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005000 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 }
5002
Amith Yamasani483f3b02012-03-13 16:08:00 -07005003 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
5004 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005005 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02005007 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005008 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005009 }
5010
Kenny Root60f7ad82011-03-22 12:49:06 -07005011 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005012 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005013 if (!sUserManager.exists(userId)) return null;
Mihai Predaeae850c2009-05-13 10:13:48 +02005014 if (packageActivities == null) {
5015 return null;
5016 }
5017 mFlags = flags;
5018 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08005019 final int N = packageActivities.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005020 ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
5021 new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02005022
5023 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02005024 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02005025 intentFilters = packageActivities.get(i).intents;
5026 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005027 PackageParser.ActivityIntentInfo[] array =
5028 new PackageParser.ActivityIntentInfo[intentFilters.size()];
5029 intentFilters.toArray(array);
5030 listCut.add(array);
Mihai Predac3320db2009-05-18 20:15:32 +02005031 }
Mihai Predaeae850c2009-05-13 10:13:48 +02005032 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07005033 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02005034 }
5035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08005037 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005038 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08005039 if (DEBUG_SHOW_INFO)
5040 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 TAG, " " + type + " " +
5042 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005043 if (DEBUG_SHOW_INFO)
5044 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08005045 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02005046 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005047 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08005048 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
5049 intent.setPriority(0);
5050 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
5051 + a.className + " with priority > 0, forcing to 0");
5052 }
Kenny Root9718cf52011-02-23 16:45:26 -08005053 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 Log.v(TAG, " IntentFilter:");
5055 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5056 }
5057 if (!intent.debugCheck()) {
5058 Log.w(TAG, "==> For Activity " + a.info.name);
5059 }
5060 addFilter(intent);
5061 }
5062 }
5063
5064 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005065 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08005066 if (DEBUG_SHOW_INFO) {
5067 Log.v(TAG, " " + type + " "
5068 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
5069 : a.info.name) + ":");
5070 Log.v(TAG, " Class=" + a.info.name);
5071 }
5072 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02005073 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005075 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 Log.v(TAG, " IntentFilter:");
5077 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5078 }
5079 removeFilter(intent);
5080 }
5081 }
5082
5083 @Override
5084 protected boolean allowFilterResult(
5085 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
5086 ActivityInfo filterAi = filter.activity.info;
5087 for (int i=dest.size()-1; i>=0; i--) {
5088 ActivityInfo destAi = dest.get(i).activityInfo;
5089 if (destAi.name == filterAi.name
5090 && destAi.packageName == filterAi.packageName) {
5091 return false;
5092 }
5093 }
5094 return true;
5095 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005098 protected ActivityIntentInfo[] newArray(int size) {
5099 return new ActivityIntentInfo[size];
5100 }
5101
5102 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005103 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005104 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005105 PackageParser.Package p = filter.activity.owner;
5106 if (p != null) {
5107 PackageSetting ps = (PackageSetting)p.mExtras;
5108 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005109 // System apps are never considered stopped for purposes of
5110 // filtering, because there may be no way for the user to
5111 // actually re-launch them.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005112 return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
5113 && ps.getStopped(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005114 }
5115 }
5116 return false;
5117 }
5118
5119 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005120 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
5121 return info.activity.owner.packageName;
5122 }
5123
5124 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005126 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005127 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005128 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 return null;
5130 }
5131 final PackageParser.Activity activity = info.activity;
5132 if (mSafeMode && (activity.info.applicationInfo.flags
5133 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5134 return null;
5135 }
Amith Yamasani13593602012-03-22 16:16:17 -07005136 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005137 if (ps == null) {
5138 return null;
5139 }
5140 ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
5141 ps.readUserState(userId), userId);
5142 if (ai == null) {
5143 return null;
5144 }
5145 final ResolveInfo res = new ResolveInfo();
5146 res.activityInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
5148 res.filter = info;
5149 }
5150 res.priority = info.getPriority();
5151 res.preferredOrder = activity.owner.mPreferredOrder;
5152 //System.out.println("Result: " + res.activityInfo.className +
5153 // " = " + res.priority);
5154 res.match = match;
5155 res.isDefault = info.hasDefault;
5156 res.labelRes = info.labelRes;
5157 res.nonLocalizedLabel = info.nonLocalizedLabel;
5158 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005159 res.system = isSystemApp(res.activityInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 return res;
5161 }
5162
5163 @Override
5164 protected void sortResults(List<ResolveInfo> results) {
5165 Collections.sort(results, mResolvePrioritySorter);
5166 }
5167
5168 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005169 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005171 out.print(prefix); out.print(
5172 Integer.toHexString(System.identityHashCode(filter.activity)));
5173 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005174 out.print(filter.activity.getComponentShortName());
5175 out.print(" filter ");
5176 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 }
5178
5179// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
5180// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
5181// final List<ResolveInfo> retList = Lists.newArrayList();
5182// while (i.hasNext()) {
5183// final ResolveInfo resolveInfo = i.next();
5184// if (isEnabledLP(resolveInfo.activityInfo)) {
5185// retList.add(resolveInfo);
5186// }
5187// }
5188// return retList;
5189// }
5190
5191 // Keys are String (activity class name), values are Activity.
5192 private final HashMap<ComponentName, PackageParser.Activity> mActivities
5193 = new HashMap<ComponentName, PackageParser.Activity>();
5194 private int mFlags;
5195 }
5196
5197 private final class ServiceIntentResolver
5198 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07005199 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005200 boolean defaultOnly, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005202 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 }
5204
Amith Yamasani483f3b02012-03-13 16:08:00 -07005205 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
5206 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005207 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005208 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02005209 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005210 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005211 }
5212
Kenny Root60f7ad82011-03-22 12:49:06 -07005213 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005214 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005215 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005216 if (packageServices == null) {
5217 return null;
5218 }
5219 mFlags = flags;
5220 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08005221 final int N = packageServices.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005222 ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
5223 new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005224
5225 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
5226 for (int i = 0; i < N; ++i) {
5227 intentFilters = packageServices.get(i).intents;
5228 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005229 PackageParser.ServiceIntentInfo[] array =
5230 new PackageParser.ServiceIntentInfo[intentFilters.size()];
5231 intentFilters.toArray(array);
5232 listCut.add(array);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005233 }
5234 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07005235 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07005236 }
5237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005239 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08005240 if (DEBUG_SHOW_INFO) {
5241 Log.v(TAG, " "
5242 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005244 Log.v(TAG, " Class=" + s.info.name);
5245 }
5246 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 int j;
5248 for (j=0; j<NI; j++) {
5249 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005250 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 Log.v(TAG, " IntentFilter:");
5252 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5253 }
5254 if (!intent.debugCheck()) {
5255 Log.w(TAG, "==> For Service " + s.info.name);
5256 }
5257 addFilter(intent);
5258 }
5259 }
5260
5261 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005262 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08005263 if (DEBUG_SHOW_INFO) {
5264 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08005266 Log.v(TAG, " Class=" + s.info.name);
5267 }
5268 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 int j;
5270 for (j=0; j<NI; j++) {
5271 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08005272 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 Log.v(TAG, " IntentFilter:");
5274 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
5275 }
5276 removeFilter(intent);
5277 }
5278 }
5279
5280 @Override
5281 protected boolean allowFilterResult(
5282 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
5283 ServiceInfo filterSi = filter.service.info;
5284 for (int i=dest.size()-1; i>=0; i--) {
5285 ServiceInfo destAi = dest.get(i).serviceInfo;
5286 if (destAi.name == filterSi.name
5287 && destAi.packageName == filterSi.packageName) {
5288 return false;
5289 }
5290 }
5291 return true;
5292 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005295 protected PackageParser.ServiceIntentInfo[] newArray(int size) {
5296 return new PackageParser.ServiceIntentInfo[size];
5297 }
5298
5299 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005300 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005301 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005302 PackageParser.Package p = filter.service.owner;
5303 if (p != null) {
5304 PackageSetting ps = (PackageSetting)p.mExtras;
5305 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005306 // System apps are never considered stopped for purposes of
5307 // filtering, because there may be no way for the user to
5308 // actually re-launch them.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005309 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
5310 && ps.getStopped(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005311 }
5312 }
5313 return false;
5314 }
5315
5316 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005317 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
5318 return info.service.owner.packageName;
5319 }
5320
5321 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005323 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005324 if (!sUserManager.exists(userId)) return null;
Jason parksa3cdaa52011-01-13 14:15:43 -06005325 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005326 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 return null;
5328 }
5329 final PackageParser.Service service = info.service;
5330 if (mSafeMode && (service.info.applicationInfo.flags
5331 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5332 return null;
5333 }
Amith Yamasani13593602012-03-22 16:16:17 -07005334 PackageSetting ps = (PackageSetting) service.owner.mExtras;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005335 if (ps == null) {
5336 return null;
5337 }
5338 ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
5339 ps.readUserState(userId), userId);
Dianne Hackborn4428e172012-08-24 17:43:05 -07005340 if (si == null) {
5341 return null;
5342 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005343 final ResolveInfo res = new ResolveInfo();
5344 res.serviceInfo = si;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
5346 res.filter = filter;
5347 }
5348 res.priority = info.getPriority();
5349 res.preferredOrder = service.owner.mPreferredOrder;
5350 //System.out.println("Result: " + res.activityInfo.className +
5351 // " = " + res.priority);
5352 res.match = match;
5353 res.isDefault = info.hasDefault;
5354 res.labelRes = info.labelRes;
5355 res.nonLocalizedLabel = info.nonLocalizedLabel;
5356 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005357 res.system = isSystemApp(res.serviceInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 return res;
5359 }
5360
5361 @Override
5362 protected void sortResults(List<ResolveInfo> results) {
5363 Collections.sort(results, mResolvePrioritySorter);
5364 }
5365
5366 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005367 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005369 out.print(prefix); out.print(
5370 Integer.toHexString(System.identityHashCode(filter.service)));
5371 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005372 out.print(filter.service.getComponentShortName());
5373 out.print(" filter ");
5374 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 }
5376
5377// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
5378// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
5379// final List<ResolveInfo> retList = Lists.newArrayList();
5380// while (i.hasNext()) {
5381// final ResolveInfo resolveInfo = (ResolveInfo) i;
5382// if (isEnabledLP(resolveInfo.serviceInfo)) {
5383// retList.add(resolveInfo);
5384// }
5385// }
5386// return retList;
5387// }
5388
5389 // Keys are String (activity class name), values are Activity.
5390 private final HashMap<ComponentName, PackageParser.Service> mServices
5391 = new HashMap<ComponentName, PackageParser.Service>();
5392 private int mFlags;
5393 };
5394
5395 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
5396 new Comparator<ResolveInfo>() {
5397 public int compare(ResolveInfo r1, ResolveInfo r2) {
5398 int v1 = r1.priority;
5399 int v2 = r2.priority;
5400 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
5401 if (v1 != v2) {
5402 return (v1 > v2) ? -1 : 1;
5403 }
5404 v1 = r1.preferredOrder;
5405 v2 = r2.preferredOrder;
5406 if (v1 != v2) {
5407 return (v1 > v2) ? -1 : 1;
5408 }
5409 if (r1.isDefault != r2.isDefault) {
5410 return r1.isDefault ? -1 : 1;
5411 }
5412 v1 = r1.match;
5413 v2 = r2.match;
5414 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005415 if (v1 != v2) {
5416 return (v1 > v2) ? -1 : 1;
5417 }
5418 if (r1.system != r2.system) {
5419 return r1.system ? -1 : 1;
5420 }
5421 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 }
5423 };
5424
5425 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
5426 new Comparator<ProviderInfo>() {
5427 public int compare(ProviderInfo p1, ProviderInfo p2) {
5428 final int v1 = p1.initOrder;
5429 final int v2 = p2.initOrder;
5430 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
5431 }
5432 };
5433
Kenny Root447106f2011-03-23 11:00:15 -07005434 static final void sendPackageBroadcast(String action, String pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005435 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
5436 int[] userIds) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 IActivityManager am = ActivityManagerNative.getDefault();
5438 if (am != null) {
5439 try {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005440 if (userIds == null) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07005441 userIds = am.getRunningUserIds();
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005442 }
Amith Yamasani13593602012-03-22 16:16:17 -07005443 for (int id : userIds) {
5444 final Intent intent = new Intent(action,
5445 pkg != null ? Uri.fromParts("package", pkg, null) : null);
5446 if (extras != null) {
5447 intent.putExtras(extras);
5448 }
5449 if (targetPkg != null) {
5450 intent.setPackage(targetPkg);
5451 }
5452 // Modify the UID when posting to other users
5453 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005454 if (uid > 0 && UserHandle.getUserId(uid) != id) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07005455 uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
Amith Yamasani13593602012-03-22 16:16:17 -07005456 intent.putExtra(Intent.EXTRA_UID, uid);
5457 }
Dianne Hackbornc72fc672012-09-20 13:12:03 -07005458 intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
Amith Yamasani13593602012-03-22 16:16:17 -07005459 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005460 if (DEBUG_BROADCASTS) {
5461 RuntimeException here = new RuntimeException("here");
5462 here.fillInStackTrace();
5463 Slog.d(TAG, "Sending to user " + id + ": "
5464 + intent.toShortString(false, true, false, false)
5465 + " " + intent.getExtras(), here);
5466 }
Amith Yamasani13593602012-03-22 16:16:17 -07005467 am.broadcastIntent(null, intent, null, finishedReceiver,
Dianne Hackbornf51f6122013-02-04 18:23:34 -08005468 0, null, null, null, android.app.AppOpsManager.OP_NONE,
5469 finishedReceiver != null, false, id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 } catch (RemoteException ex) {
5472 }
5473 }
5474 }
Kenny Root300c13a2011-01-18 13:04:40 -08005475
5476 /**
5477 * Check if the external storage media is available. This is true if there
5478 * is a mounted external storage medium or if the external storage is
5479 * emulated.
5480 */
5481 private boolean isExternalMediaAvailable() {
5482 return mMediaMounted || Environment.isExternalStorageEmulated();
5483 }
5484
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005485 public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07005486 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005487 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005488 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005489 // If the external storage is no longer mounted at this point,
5490 // the caller may not have been able to delete all of this
5491 // packages files and can not delete any more. Bail.
5492 return null;
5493 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07005494 final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
5495 if (lastPackage != null) {
5496 pkgs.remove(lastPackage);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005497 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07005498 if (pkgs.size() > 0) {
5499 return pkgs.get(0);
5500 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005501 }
5502 return null;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005505 void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
5506 if (false) {
5507 RuntimeException here = new RuntimeException("here");
5508 here.fillInStackTrace();
5509 Slog.d(TAG, "Schedule cleaning " + packageName + " user=" + userId
5510 + " andCode=" + andCode, here);
5511 }
5512 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE,
5513 userId, andCode ? 1 : 0, packageName));
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005514 }
5515
Jeff Sharkey752cd922012-09-23 16:25:12 -07005516 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07005517 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005518 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005519 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005520 return;
5521 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07005522 if (mSettings.mPackagesToBeCleaned.isEmpty()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005523 return;
5524 }
5525 }
5526 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
5527 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
5528 IActivityManager am = ActivityManagerNative.getDefault();
5529 if (am != null) {
5530 try {
Jeff Sharkey752cd922012-09-23 16:25:12 -07005531 am.startService(null, intent, null, UserHandle.USER_OWNER);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005532 } catch (RemoteException e) {
5533 }
5534 }
5535 }
5536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 private final class AppDirObserver extends FileObserver {
5538 public AppDirObserver(String path, int mask, boolean isrom) {
5539 super(path, mask);
5540 mRootDir = path;
5541 mIsRom = isrom;
5542 }
5543
5544 public void onEvent(int event, String path) {
5545 String removedPackage = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005546 int removedAppId = -1;
Dianne Hackborn786b4402012-08-27 15:14:02 -07005547 int[] removedUsers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 String addedPackage = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005549 int addedAppId = -1;
Dianne Hackborn786b4402012-08-27 15:14:02 -07005550 int[] addedUsers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551
Kenny Root447106f2011-03-23 11:00:15 -07005552 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 synchronized (mInstallLock) {
5554 String fullPathStr = null;
5555 File fullPath = null;
5556 if (path != null) {
5557 fullPath = new File(mRootDir, path);
5558 fullPathStr = fullPath.getPath();
5559 }
5560
Kenny Root9718cf52011-02-23 16:45:26 -08005561 if (DEBUG_APP_DIR_OBSERVER)
5562 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563
5564 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08005565 if (DEBUG_APP_DIR_OBSERVER)
5566 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 return;
5568 }
5569
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005570 // Ignore packages that are being installed or
5571 // have just been installed.
5572 if (ignoreCodePath(fullPathStr)) {
5573 return;
5574 }
5575 PackageParser.Package p = null;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005576 PackageSetting ps = null;
Kenny Root447106f2011-03-23 11:00:15 -07005577 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005578 synchronized (mPackages) {
5579 p = mAppDirs.get(fullPathStr);
Dianne Hackborn786b4402012-08-27 15:14:02 -07005580 if (p != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005581 ps = mSettings.mPackages.get(p.applicationInfo.packageName);
Dianne Hackborn786b4402012-08-27 15:14:02 -07005582 if (ps != null) {
5583 removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
5584 } else {
5585 removedUsers = sUserManager.getUserIds();
5586 }
5587 }
5588 addedUsers = sUserManager.getUserIds();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 if ((event&REMOVE_EVENTS) != 0) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005591 if (ps != null) {
5592 removePackageLI(ps, true);
5593 removedPackage = ps.name;
5594 removedAppId = ps.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 }
5596 }
5597
5598 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005600 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07005601 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
5602 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 PackageParser.PARSE_CHATTY |
5604 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005605 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
Dianne Hackborn786b4402012-08-27 15:14:02 -07005606 System.currentTimeMillis(), UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005608 /*
5609 * TODO this seems dangerous as the package may have
5610 * changed since we last acquired the mPackages
5611 * lock.
5612 */
5613 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005615 updatePermissionsLPw(p.packageName, p,
Dianne Hackborne639da72012-02-21 15:11:13 -08005616 p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 }
5618 addedPackage = p.applicationInfo.packageName;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005619 addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 }
5621 }
5622 }
5623
Kenny Root447106f2011-03-23 11:00:15 -07005624 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005626 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 }
5628 }
5629
5630 if (removedPackage != null) {
5631 Bundle extras = new Bundle(1);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005632 extras.putInt(Intent.EXTRA_UID, removedAppId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005634 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborn786b4402012-08-27 15:14:02 -07005635 extras, null, null, removedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 }
5637 if (addedPackage != null) {
5638 Bundle extras = new Bundle(1);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07005639 extras.putInt(Intent.EXTRA_UID, addedAppId);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005640 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Dianne Hackborn786b4402012-08-27 15:14:02 -07005641 extras, null, null, addedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 }
5643 }
5644
5645 private final String mRootDir;
5646 private final boolean mIsRom;
5647 }
Jacek Surazski65e13172009-04-28 15:26:38 +02005648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 /* Called when a downloaded package installation has been confirmed by the user */
5650 public void installPackage(
5651 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02005652 installPackage(packageURI, observer, flags, null);
5653 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005654
Jacek Surazski65e13172009-04-28 15:26:38 +02005655 /* Called when a downloaded package installation has been confirmed by the user */
5656 public void installPackage(
5657 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
5658 final String installerPackageName) {
Kenny Root5ab21572011-07-27 11:11:19 -07005659 installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
Rich Canningse1d7c712012-08-08 12:46:06 -07005660 null, null);
Kenny Root5ab21572011-07-27 11:11:19 -07005661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005662
Kenny Root5ab21572011-07-27 11:11:19 -07005663 @Override
5664 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
5665 int flags, String installerPackageName, Uri verificationURI,
Rich Canningse1d7c712012-08-08 12:46:06 -07005666 ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
rich cannings706e8ba2012-08-20 13:20:14 -07005667 VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
Ben Gruver37d83a32012-09-27 13:02:06 -07005668 VerificationParams.NO_UID, manifestDigest);
rich cannings706e8ba2012-08-20 13:20:14 -07005669 installPackageWithVerificationAndEncryption(packageURI, observer, flags,
5670 installerPackageName, verificationParams, encryptionParams);
5671 }
5672
5673 public void installPackageWithVerificationAndEncryption(Uri packageURI,
5674 IPackageInstallObserver observer, int flags, String installerPackageName,
5675 VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
5676 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
5677 null);
Kenny Root5ab21572011-07-27 11:11:19 -07005678
5679 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08005680 if (!isUserAllowed(UserHandle.getUserId(uid), UserManager.ALLOW_INSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08005681 try {
5682 observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
5683 } catch (RemoteException re) {
5684 }
5685 return;
5686 }
5687
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005688 UserHandle user;
5689 if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
5690 user = UserHandle.ALL;
5691 } else {
Dianne Hackborn786b4402012-08-27 15:14:02 -07005692 user = new UserHandle(UserHandle.getUserId(uid));
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005693 }
Kenny Root5ab21572011-07-27 11:11:19 -07005694
5695 final int filteredFlags;
5696
5697 if (uid == Process.SHELL_UID || uid == 0) {
5698 if (DEBUG_INSTALL) {
5699 Slog.v(TAG, "Install from ADB");
5700 }
5701 filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
5702 } else {
5703 filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
5704 }
5705
rich cannings13d428e2012-09-13 13:43:07 -07005706 verificationParams.setInstallerUid(uid);
5707
Kenny Root5ab21572011-07-27 11:11:19 -07005708 final Message msg = mHandler.obtainMessage(INIT_COPY);
5709 msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005710 verificationParams, encryptionParams, user);
Kenny Root5ab21572011-07-27 11:11:19 -07005711 mHandler.sendMessage(msg);
5712 }
5713
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005714 /**
5715 * @hide
5716 */
5717 @Override
Amith Yamasani67df64b2012-12-14 12:09:36 -08005718 public int installExistingPackageAsUser(String packageName, int userId) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005719 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
5720 null);
5721 PackageSetting pkgSetting;
5722 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08005723 if (UserHandle.getUserId(uid) != userId) {
5724 mContext.enforceCallingPermission(
5725 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
5726 "installExistingPackage for user " + userId);
5727 }
5728 if (!isUserAllowed(userId, UserManager.ALLOW_INSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08005729 return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
5730 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005731
5732 long callingId = Binder.clearCallingIdentity();
5733 try {
5734 boolean sendAdded = false;
5735 Bundle extras = new Bundle(1);
5736
5737 // writer
5738 synchronized (mPackages) {
5739 pkgSetting = mSettings.mPackages.get(packageName);
5740 if (pkgSetting == null) {
5741 return PackageManager.INSTALL_FAILED_INVALID_URI;
5742 }
5743 if (!pkgSetting.getInstalled(userId)) {
5744 pkgSetting.setInstalled(true, userId);
5745 mSettings.writePackageRestrictionsLPr(userId);
5746 extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
5747 sendAdded = true;
5748 }
5749 }
5750
5751 if (sendAdded) {
5752 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
5753 packageName, extras, null, null, new int[] {userId});
5754 }
5755 } finally {
5756 Binder.restoreCallingIdentity(callingId);
5757 }
5758
5759 return PackageManager.INSTALL_SUCCEEDED;
5760 }
Amith Yamasanie4cf7342012-12-17 11:12:09 -08005761
Amith Yamasani67df64b2012-12-14 12:09:36 -08005762 private boolean isUserAllowed(int userId, String restrictionKey) {
5763 Bundle restrictions = sUserManager.getUserRestrictions(userId);
5764 if (!restrictions.getBoolean(UserManager.ALLOW_INSTALL_APPS)) {
5765 Log.w(TAG, "User does not have permission to: " + restrictionKey);
5766 return false;
Amith Yamasanie4cf7342012-12-17 11:12:09 -08005767 }
5768 return true;
5769 }
5770
Kenny Root5ab21572011-07-27 11:11:19 -07005771 @Override
Kenny Root05ca4c92011-09-15 10:36:25 -07005772 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
rich cannings7e671512012-08-27 14:44:16 -07005773 mContext.enforceCallingOrSelfPermission(
5774 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
5775 "Only package verification agents can verify applications");
5776
Kenny Root5ab21572011-07-27 11:11:19 -07005777 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
Kenny Root05ca4c92011-09-15 10:36:25 -07005778 final PackageVerificationResponse response = new PackageVerificationResponse(
5779 verificationCode, Binder.getCallingUid());
Kenny Root5ab21572011-07-27 11:11:19 -07005780 msg.arg1 = id;
Kenny Root05ca4c92011-09-15 10:36:25 -07005781 msg.obj = response;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005782 mHandler.sendMessage(msg);
5783 }
5784
rich canningsd9ef3e52012-08-22 14:28:05 -07005785 @Override
5786 public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
5787 long millisecondsToDelay) {
rich cannings7e671512012-08-27 14:44:16 -07005788 mContext.enforceCallingOrSelfPermission(
5789 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
5790 "Only package verification agents can extend verification timeouts");
5791
rich canningsd9ef3e52012-08-22 14:28:05 -07005792 final PackageVerificationState state = mPendingVerification.get(id);
5793 final PackageVerificationResponse response = new PackageVerificationResponse(
5794 verificationCodeAtTimeout, Binder.getCallingUid());
5795
rich canningsd1b5cfc2012-08-29 14:49:51 -07005796 if (millisecondsToDelay > PackageManager.MAXIMUM_VERIFICATION_TIMEOUT) {
5797 millisecondsToDelay = PackageManager.MAXIMUM_VERIFICATION_TIMEOUT;
5798 }
5799 if (millisecondsToDelay < 0) {
5800 millisecondsToDelay = 0;
rich canningsd9ef3e52012-08-22 14:28:05 -07005801 }
5802 if ((verificationCodeAtTimeout != PackageManager.VERIFICATION_ALLOW)
rich canningsd1b5cfc2012-08-29 14:49:51 -07005803 && (verificationCodeAtTimeout != PackageManager.VERIFICATION_REJECT)) {
5804 verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
rich canningsd9ef3e52012-08-22 14:28:05 -07005805 }
5806
5807 if ((state != null) && !state.timeoutExtended()) {
5808 state.extendTimeout();
5809
5810 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
5811 msg.arg1 = id;
5812 msg.obj = response;
5813 mHandler.sendMessageDelayed(msg, millisecondsToDelay);
5814 }
5815 }
5816
rich canningsd1b5cfc2012-08-29 14:49:51 -07005817 private void broadcastPackageVerified(int verificationId, Uri packageUri,
rich canningsd55deb02012-10-02 14:53:08 -07005818 int verificationCode, UserHandle user) {
rich canningsd1b5cfc2012-08-29 14:49:51 -07005819 final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
5820 intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
5821 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
5822 intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
5823 intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode);
5824
rich canningsd55deb02012-10-02 14:53:08 -07005825 mContext.sendBroadcastAsUser(intent, user,
5826 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
rich canningsd1b5cfc2012-08-29 14:49:51 -07005827 }
5828
Kenny Root05ca4c92011-09-15 10:36:25 -07005829 private ComponentName matchComponentForVerifier(String packageName,
5830 List<ResolveInfo> receivers) {
5831 ActivityInfo targetReceiver = null;
5832
5833 final int NR = receivers.size();
5834 for (int i = 0; i < NR; i++) {
5835 final ResolveInfo info = receivers.get(i);
5836 if (info.activityInfo == null) {
5837 continue;
5838 }
5839
5840 if (packageName.equals(info.activityInfo.packageName)) {
5841 targetReceiver = info.activityInfo;
5842 break;
5843 }
5844 }
5845
5846 if (targetReceiver == null) {
5847 return null;
5848 }
5849
5850 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
5851 }
5852
5853 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
5854 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
5855 if (pkgInfo.verifiers.length == 0) {
5856 return null;
5857 }
5858
5859 final int N = pkgInfo.verifiers.length;
5860 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
5861 for (int i = 0; i < N; i++) {
5862 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
5863
5864 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
5865 receivers);
5866 if (comp == null) {
5867 continue;
5868 }
5869
5870 final int verifierUid = getUidForVerifier(verifierInfo);
5871 if (verifierUid == -1) {
5872 continue;
5873 }
5874
5875 if (DEBUG_VERIFY) {
5876 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
5877 + " with the correct signature");
5878 }
5879 sufficientVerifiers.add(comp);
5880 verificationState.addSufficientVerifier(verifierUid);
5881 }
5882
5883 return sufficientVerifiers;
5884 }
5885
5886 private int getUidForVerifier(VerifierInfo verifierInfo) {
5887 synchronized (mPackages) {
5888 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
5889 if (pkg == null) {
5890 return -1;
5891 } else if (pkg.mSignatures.length != 1) {
5892 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5893 + " has more than one signature; ignoring");
5894 return -1;
5895 }
5896
5897 /*
5898 * If the public key of the package's signature does not match
5899 * our expected public key, then this is a different package and
5900 * we should skip.
5901 */
5902
5903 final byte[] expectedPublicKey;
5904 try {
5905 final Signature verifierSig = pkg.mSignatures[0];
5906 final PublicKey publicKey = verifierSig.getPublicKey();
5907 expectedPublicKey = publicKey.getEncoded();
5908 } catch (CertificateException e) {
5909 return -1;
5910 }
5911
5912 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
5913
5914 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
5915 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5916 + " does not have the expected public key; ignoring");
5917 return -1;
5918 }
5919
5920 return pkg.applicationInfo.uid;
5921 }
5922 }
5923
Christopher Tate1bb69062010-02-19 17:02:12 -08005924 public void finishPackageInstall(int token) {
Kenny Root461ff1f2011-08-09 09:43:03 -07005925 enforceSystemOrRoot("Only the system is allowed to finish installs");
5926
5927 if (DEBUG_INSTALL) {
5928 Slog.v(TAG, "BM finishing package install for " + token);
5929 }
5930
5931 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
Christopher Tate1bb69062010-02-19 17:02:12 -08005932 mHandler.sendMessage(msg);
5933 }
5934
Kenny Root5ab21572011-07-27 11:11:19 -07005935 /**
5936 * Get the verification agent timeout.
5937 *
5938 * @return verification timeout in milliseconds
5939 */
5940 private long getVerificationTimeout() {
rich cannings4d8fc792012-09-07 14:43:43 -07005941 return android.provider.Settings.Global.getLong(mContext.getContentResolver(),
5942 android.provider.Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
Kenny Root5ab21572011-07-27 11:11:19 -07005943 DEFAULT_VERIFICATION_TIMEOUT);
5944 }
5945
5946 /**
rich canningsa6cfe522012-05-21 15:50:56 -07005947 * Get the default verification agent response code.
5948 *
5949 * @return default verification response code
5950 */
5951 private int getDefaultVerificationResponse() {
rich cannings4d8fc792012-09-07 14:43:43 -07005952 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
5953 android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
rich canningsa6cfe522012-05-21 15:50:56 -07005954 DEFAULT_VERIFICATION_RESPONSE);
5955 }
5956
5957 /**
Kenny Root5ab21572011-07-27 11:11:19 -07005958 * Check whether or not package verification has been enabled.
5959 *
5960 * @return true if verification should be performed
5961 */
rich cannings4e5753f2012-09-19 16:03:56 -07005962 private boolean isVerificationEnabled(int flags) {
rich canningse4bf0ea2012-09-14 13:18:55 -07005963 if (!DEFAULT_VERIFY_ENABLE) {
5964 return false;
5965 }
5966
rich cannings4e5753f2012-09-19 16:03:56 -07005967 // Check if installing from ADB
5968 if ((flags & PackageManager.INSTALL_FROM_ADB) != 0) {
rich canningsa2064df2012-09-30 14:52:41 -07005969 // Do not run verification in a test harness environment
5970 if (ActivityManager.isRunningInTestHarness()) {
5971 return false;
5972 }
rich cannings4e5753f2012-09-19 16:03:56 -07005973 // Check if the developer does not want package verification for ADB installs
5974 if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
5975 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
5976 return false;
5977 }
5978 }
5979
rich cannings4d8fc792012-09-07 14:43:43 -07005980 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
rich canningse4bf0ea2012-09-14 13:18:55 -07005981 android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
Kenny Root5ab21572011-07-27 11:11:19 -07005982 }
5983
Matt Finifterf8a98ed2012-05-14 15:43:34 -07005984 /**
5985 * Get the "allow unknown sources" setting.
5986 *
5987 * @return the current "allow unknown sources" setting
5988 */
5989 private int getUnknownSourcesSettings() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -07005990 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
5991 android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
Matt Finifterf8a98ed2012-05-14 15:43:34 -07005992 -1);
5993 }
5994
Kenny Rootf03b45f2011-02-23 17:25:45 -08005995 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08005996 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07005997 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08005998 synchronized (mPackages) {
5999 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
6000 if (targetPackageSetting == null) {
6001 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
6002 }
6003
6004 PackageSetting installerPackageSetting;
6005 if (installerPackageName != null) {
6006 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
6007 if (installerPackageSetting == null) {
6008 throw new IllegalArgumentException("Unknown installer package: "
6009 + installerPackageName);
6010 }
6011 } else {
6012 installerPackageSetting = null;
6013 }
6014
6015 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07006016 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08006017 if (obj != null) {
6018 if (obj instanceof SharedUserSetting) {
6019 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
6020 } else if (obj instanceof PackageSetting) {
6021 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
6022 } else {
6023 throw new SecurityException("Bad object " + obj + " for uid " + uid);
6024 }
6025 } else {
6026 throw new SecurityException("Unknown calling uid " + uid);
6027 }
6028
6029 // Verify: can't set installerPackageName to a package that is
6030 // not signed with the same cert as the caller.
6031 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07006032 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08006033 installerPackageSetting.signatures.mSignatures)
6034 != PackageManager.SIGNATURE_MATCH) {
6035 throw new SecurityException(
6036 "Caller does not have same cert as new installer package "
6037 + installerPackageName);
6038 }
6039 }
6040
6041 // Verify: if target already has an installer package, it must
6042 // be signed with the same cert as the caller.
6043 if (targetPackageSetting.installerPackageName != null) {
6044 PackageSetting setting = mSettings.mPackages.get(
6045 targetPackageSetting.installerPackageName);
6046 // If the currently set package isn't valid, then it's always
6047 // okay to change it.
6048 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07006049 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08006050 setting.signatures.mSignatures)
6051 != PackageManager.SIGNATURE_MATCH) {
6052 throw new SecurityException(
6053 "Caller does not have same cert as old installer package "
6054 + targetPackageSetting.installerPackageName);
6055 }
6056 }
6057 }
6058
6059 // Okay!
6060 targetPackageSetting.installerPackageName = installerPackageName;
6061 scheduleWriteSettingsLocked();
6062 }
6063 }
6064
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006065 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 // Queue up an async operation since the package installation may take a little while.
6067 mHandler.post(new Runnable() {
6068 public void run() {
6069 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006070 // Result object to be returned
6071 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006072 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006073 res.uid = -1;
6074 res.pkg = null;
6075 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006076 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07006077 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006078 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006079 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006080 }
Kenny Root6dceb882012-04-12 14:23:49 -07006081 args.doPostInstall(res.returnCode, res.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006082 }
Christopher Tate1bb69062010-02-19 17:02:12 -08006083
6084 // A restore should be performed at this point if (a) the install
6085 // succeeded, (b) the operation is not an update, and (c) the new
6086 // package has a backupAgent defined.
6087 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08006088 boolean doRestore = (!update
6089 && res.pkg != null
6090 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08006091
6092 // Set up the post-install work request bookkeeping. This will be used
6093 // and cleaned up by the post-install event handling regardless of whether
6094 // there's a restore pass performed. Token values are >= 1.
6095 int token;
6096 if (mNextInstallToken < 0) mNextInstallToken = 1;
6097 token = mNextInstallToken++;
6098
6099 PostInstallData data = new PostInstallData(args, res);
6100 mRunningInstalls.put(token, data);
6101 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
6102
6103 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
6104 // Pass responsibility to the Backup Manager. It will perform a
6105 // restore if appropriate, then pass responsibility back to the
6106 // Package Manager to run the post-install observer callbacks
6107 // and broadcasts.
6108 IBackupManager bm = IBackupManager.Stub.asInterface(
6109 ServiceManager.getService(Context.BACKUP_SERVICE));
6110 if (bm != null) {
6111 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
6112 + " to BM for possible restore");
6113 try {
6114 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
6115 } catch (RemoteException e) {
6116 // can't happen; the backup manager is local
6117 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006118 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08006119 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006120 }
Christopher Tate1bb69062010-02-19 17:02:12 -08006121 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006122 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08006123 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 }
Christopher Tate1bb69062010-02-19 17:02:12 -08006126
6127 if (!doRestore) {
6128 // No restore possible, or the Backup Manager was mysteriously not
6129 // available -- just fire the post-install work request directly.
6130 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
6131 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
6132 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006134 }
6135 });
6136 }
6137
Kenny Root5ab21572011-07-27 11:11:19 -07006138 private abstract class HandlerParams {
6139 private static final int MAX_RETRIES = 4;
6140
6141 /**
6142 * Number of times startCopy() has been attempted and had a non-fatal
6143 * error.
6144 */
6145 private int mRetries = 0;
6146
Amith Yamasani6ec10122012-08-23 13:49:25 -07006147 /** User handle for the user requesting the information or installation. */
6148 private final UserHandle mUser;
6149
6150 HandlerParams(UserHandle user) {
6151 mUser = user;
6152 }
6153
6154 UserHandle getUser() {
6155 return mUser;
6156 }
6157
Dianne Hackborn7d608422011-08-07 16:24:18 -07006158 final boolean startCopy() {
6159 boolean res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006160 try {
Kenny Root5ab21572011-07-27 11:11:19 -07006161 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
6162
6163 if (++mRetries > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006164 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006165 mHandler.sendEmptyMessage(MCS_GIVE_UP);
6166 handleServiceError();
Dianne Hackborn7d608422011-08-07 16:24:18 -07006167 return false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006168 } else {
6169 handleStartCopy();
Dianne Hackborn7d608422011-08-07 16:24:18 -07006170 res = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006171 }
6172 } catch (RemoteException e) {
Kenny Root5ab21572011-07-27 11:11:19 -07006173 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006174 mHandler.sendEmptyMessage(MCS_RECONNECT);
Dianne Hackborn7d608422011-08-07 16:24:18 -07006175 res = false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006176 }
6177 handleReturnCode();
Dianne Hackborn7d608422011-08-07 16:24:18 -07006178 return res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006179 }
6180
6181 final void serviceError() {
Kenny Root5ab21572011-07-27 11:11:19 -07006182 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006183 handleServiceError();
6184 handleReturnCode();
6185 }
Kenny Root5ab21572011-07-27 11:11:19 -07006186
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006187 abstract void handleStartCopy() throws RemoteException;
6188 abstract void handleServiceError();
6189 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006190 }
6191
Kenny Root366949c2011-01-14 17:18:14 -08006192 class MeasureParams extends HandlerParams {
6193 private final PackageStats mStats;
6194 private boolean mSuccess;
6195
6196 private final IPackageStatsObserver mObserver;
6197
Kenny Roota69b7eb2012-05-14 14:47:06 -07006198 public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
Amith Yamasani6ec10122012-08-23 13:49:25 -07006199 super(new UserHandle(stats.userHandle));
Kenny Root366949c2011-01-14 17:18:14 -08006200 mObserver = observer;
6201 mStats = stats;
Kenny Root366949c2011-01-14 17:18:14 -08006202 }
6203
6204 @Override
6205 void handleStartCopy() throws RemoteException {
Kenny Roota69b7eb2012-05-14 14:47:06 -07006206 synchronized (mInstallLock) {
Dianne Hackborn0c380492012-08-20 17:23:30 -07006207 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
Kenny Roota69b7eb2012-05-14 14:47:06 -07006208 }
Kenny Root366949c2011-01-14 17:18:14 -08006209
Kenny Roota69b7eb2012-05-14 14:47:06 -07006210 final boolean mounted;
Kenny Root366949c2011-01-14 17:18:14 -08006211 if (Environment.isExternalStorageEmulated()) {
6212 mounted = true;
6213 } else {
6214 final String status = Environment.getExternalStorageState();
Jeff Sharkeyb049e212012-09-07 23:16:01 -07006215 mounted = (Environment.MEDIA_MOUNTED.equals(status)
6216 || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
Kenny Root366949c2011-01-14 17:18:14 -08006217 }
6218
6219 if (mounted) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07006220 final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
6221
6222 final File externalCacheDir = userEnv
Kenny Root366949c2011-01-14 17:18:14 -08006223 .getExternalStorageAppCacheDirectory(mStats.packageName);
6224 final long externalCacheSize = mContainerService
6225 .calculateDirectorySize(externalCacheDir.getPath());
6226 mStats.externalCacheSize = externalCacheSize;
6227
Jeff Sharkeyb049e212012-09-07 23:16:01 -07006228 final File externalDataDir = userEnv
Kenny Root366949c2011-01-14 17:18:14 -08006229 .getExternalStorageAppDataDirectory(mStats.packageName);
6230 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
6231 .getPath());
6232
6233 if (externalCacheDir.getParentFile().equals(externalDataDir)) {
6234 externalDataSize -= externalCacheSize;
6235 }
6236 mStats.externalDataSize = externalDataSize;
6237
Jeff Sharkeyb049e212012-09-07 23:16:01 -07006238 final File externalMediaDir = userEnv
Kenny Root366949c2011-01-14 17:18:14 -08006239 .getExternalStorageAppMediaDirectory(mStats.packageName);
6240 mStats.externalMediaSize = mContainerService
Kenny Rootc7624d92011-02-23 16:25:25 -08006241 .calculateDirectorySize(externalMediaDir.getPath());
Kenny Rootbcd6c962011-01-17 11:21:49 -08006242
Jeff Sharkeyb049e212012-09-07 23:16:01 -07006243 final File externalObbDir = userEnv
Kenny Rootbcd6c962011-01-17 11:21:49 -08006244 .getExternalStorageAppObbDirectory(mStats.packageName);
6245 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
6246 .getPath());
Kenny Root366949c2011-01-14 17:18:14 -08006247 }
6248 }
6249
6250 @Override
6251 void handleReturnCode() {
6252 if (mObserver != null) {
6253 try {
6254 mObserver.onGetStatsCompleted(mStats, mSuccess);
6255 } catch (RemoteException e) {
6256 Slog.i(TAG, "Observer no longer exists.");
6257 }
6258 }
6259 }
6260
6261 @Override
6262 void handleServiceError() {
6263 Slog.e(TAG, "Could not measure application " + mStats.packageName
6264 + " external storage");
6265 }
6266 }
6267
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006268 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006269 final IPackageInstallObserver observer;
6270 int flags;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006271
6272 private final Uri mPackageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006273 final String installerPackageName;
rich cannings706e8ba2012-08-20 13:20:14 -07006274 final VerificationParams verificationParams;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006275 private InstallArgs mArgs;
6276 private int mRet;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006277 private File mTempPackage;
6278 final ContainerEncryptionParams encryptionParams;
Kenny Root5ab21572011-07-27 11:11:19 -07006279
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006280 InstallParams(Uri packageURI,
6281 IPackageInstallObserver observer, int flags,
rich cannings706e8ba2012-08-20 13:20:14 -07006282 String installerPackageName, VerificationParams verificationParams,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006283 ContainerEncryptionParams encryptionParams, UserHandle user) {
Amith Yamasani6ec10122012-08-23 13:49:25 -07006284 super(user);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006285 this.mPackageURI = packageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006286 this.flags = flags;
6287 this.observer = observer;
6288 this.installerPackageName = installerPackageName;
rich cannings706e8ba2012-08-20 13:20:14 -07006289 this.verificationParams = verificationParams;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006290 this.encryptionParams = encryptionParams;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006291 }
6292
rich cannings706e8ba2012-08-20 13:20:14 -07006293 public ManifestDigest getManifestDigest() {
6294 if (verificationParams == null) {
6295 return null;
6296 }
6297 return verificationParams.getManifestDigest();
6298 }
6299
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006300 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
6301 String packageName = pkgLite.packageName;
6302 int installLocation = pkgLite.installLocation;
6303 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07006304 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006305 synchronized (mPackages) {
6306 PackageParser.Package pkg = mPackages.get(packageName);
6307 if (pkg != null) {
6308 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006309 // Check for downgrading.
6310 if ((flags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
6311 if (pkgLite.versionCode < pkg.mVersionCode) {
6312 Slog.w(TAG, "Can't install update of " + packageName
6313 + " update version " + pkgLite.versionCode
6314 + " is older than installed version "
6315 + pkg.mVersionCode);
6316 return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
6317 }
6318 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006319 // Check for updated system application.
6320 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6321 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006322 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006323 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
6324 }
6325 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
6326 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006327 if (onSd) {
6328 // Install flag overrides everything.
6329 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
6330 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07006331 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006332 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
6333 // Application explicitly specified internal.
6334 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
6335 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
6336 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07006337 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006338 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07006339 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07006340 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
6341 }
6342 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006343 }
6344 }
6345 } else {
6346 // Invalid install. Return error code
6347 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
6348 }
6349 }
6350 }
6351 // All the special cases have been taken care of.
6352 // Return result based on recommended install location.
6353 if (onSd) {
6354 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
6355 }
6356 return pkgLite.recommendedInstallLocation;
6357 }
6358
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006359 /*
6360 * Invoke remote method to get package information and install
6361 * location values. Override install location based on default
6362 * policy if needed and then create install arguments based
6363 * on the install location.
6364 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006365 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08006366 int ret = PackageManager.INSTALL_SUCCEEDED;
Kenny Root05ca4c92011-09-15 10:36:25 -07006367 final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
6368 final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
6369 PackageInfoLite pkgLite = null;
6370
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07006371 if (onInt && onSd) {
6372 // Check if both bits are set.
6373 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
6374 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006375 } else {
Kenny Root62e1b4e2011-03-14 17:13:39 -07006376 final long lowThreshold;
6377
6378 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
6379 .getService(DeviceStorageMonitorService.SERVICE);
6380 if (dsm == null) {
6381 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
6382 lowThreshold = 0L;
6383 } else {
6384 lowThreshold = dsm.getMemoryLowThreshold();
6385 }
6386
Kenny Root11128572010-10-11 10:51:32 -07006387 try {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006388 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
Kenny Root11128572010-10-11 10:51:32 -07006389 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root11128572010-10-11 10:51:32 -07006390
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006391 final File packageFile;
6392 if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006393 mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
6394 if (mTempPackage != null) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -08006395 ParcelFileDescriptor out;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006396 try {
6397 out = ParcelFileDescriptor.open(mTempPackage,
6398 ParcelFileDescriptor.MODE_READ_WRITE);
6399 } catch (FileNotFoundException e) {
Dianne Hackborn40e9f292012-11-27 19:12:23 -08006400 out = null;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006401 Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
6402 }
6403
6404 // Make a temporary file for decryption.
6405 ret = mContainerService
6406 .copyResource(mPackageURI, encryptionParams, out);
Dianne Hackborn40e9f292012-11-27 19:12:23 -08006407 IoUtils.closeQuietly(out);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006408
6409 packageFile = mTempPackage;
6410
6411 FileUtils.setPermissions(packageFile.getAbsolutePath(),
Kenny Root0b2fa8c2012-09-14 10:26:16 -07006412 FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP
6413 | FileUtils.S_IROTH,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006414 -1, -1);
6415 } else {
6416 packageFile = null;
6417 }
6418 } else {
6419 packageFile = new File(mPackageURI.getPath());
6420 }
6421
6422 if (packageFile != null) {
6423 // Remote call to find out default install location
Kenny Rootcea37432012-10-18 14:57:33 -07006424 final String packageFilePath = packageFile.getAbsolutePath();
6425 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
6426 lowThreshold);
6427
6428 /*
6429 * If we have too little free space, try to free cache
6430 * before giving up.
6431 */
6432 if (pkgLite.recommendedInstallLocation
6433 == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
6434 final long size = mContainerService.calculateInstalledSize(
6435 packageFilePath, isForwardLocked());
6436 if (mInstaller.freeCache(size + lowThreshold) >= 0) {
6437 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
6438 flags, lowThreshold);
6439 }
Kenny Root3f96d0e2012-12-11 12:48:08 -08006440 /*
6441 * The cache free must have deleted the file we
6442 * downloaded to install.
6443 *
6444 * TODO: fix the "freeCache" call to not delete
6445 * the file we care about.
6446 */
6447 if (pkgLite.recommendedInstallLocation
6448 == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
6449 pkgLite.recommendedInstallLocation
6450 = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
6451 }
Kenny Rootcea37432012-10-18 14:57:33 -07006452 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006453 }
6454 } finally {
6455 mContext.revokeUriPermission(mPackageURI,
6456 Intent.FLAG_GRANT_READ_URI_PERMISSION);
6457 }
6458 }
6459
6460 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006461 int loc = pkgLite.recommendedInstallLocation;
Kenny Root1ebd74a2011-08-03 15:09:44 -07006462 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006463 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Kenny Root1ebd74a2011-08-03 15:09:44 -07006464 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08006465 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
Kenny Root1ebd74a2011-08-03 15:09:44 -07006466 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006467 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6468 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
6469 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Kenny Root1ebd74a2011-08-03 15:09:44 -07006470 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
6471 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006472 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
Kenny Root1ebd74a2011-08-03 15:09:44 -07006473 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006474 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006475 // Override with defaults if needed.
6476 loc = installLocationPolicy(pkgLite, flags);
Kenny Roota3e90792012-10-18 10:58:36 -07006477 if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
6478 ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
6479 } else if (!onSd && !onInt) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07006480 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006481 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
6482 // Set the flag to install on external media.
6483 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07006484 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006485 } else {
6486 // Make sure the flag for installing on external
6487 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07006488 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006489 flags &= ~PackageManager.INSTALL_EXTERNAL;
6490 }
6491 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006492 }
6493 }
Kenny Root5ab21572011-07-27 11:11:19 -07006494
6495 final InstallArgs args = createInstallArgs(this);
Kenny Root05ca4c92011-09-15 10:36:25 -07006496 mArgs = args;
6497
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006498 if (ret == PackageManager.INSTALL_SUCCEEDED) {
rich cannings36070b42012-10-09 11:50:15 -07006499 /*
6500 * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
6501 * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
6502 */
6503 int userIdentifier = getUser().getIdentifier();
6504 if (userIdentifier == UserHandle.USER_ALL
6505 && ((flags & PackageManager.INSTALL_FROM_ADB) != 0)) {
6506 userIdentifier = UserHandle.USER_OWNER;
6507 }
6508
Kenny Root5ab21572011-07-27 11:11:19 -07006509 /*
6510 * Determine if we have any installed package verifiers. If we
6511 * do, then we'll defer to them to verify the packages.
6512 */
Kenny Root05ca4c92011-09-15 10:36:25 -07006513 final int requiredUid = mRequiredVerifierPackage == null ? -1
rich cannings36070b42012-10-09 11:50:15 -07006514 : getPackageUid(mRequiredVerifierPackage, userIdentifier);
rich cannings4e5753f2012-09-19 16:03:56 -07006515 if (requiredUid != -1 && isVerificationEnabled(flags)) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006516 final Intent verification = new Intent(
6517 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
6518 verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
Kenny Root05ca4c92011-09-15 10:36:25 -07006519 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root5ab21572011-07-27 11:11:19 -07006520
Andy Stadler250ce282012-08-24 16:09:03 -07006521 final List<ResolveInfo> receivers = queryIntentReceivers(verification,
6522 PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
6523 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07006524
6525 if (DEBUG_VERIFY) {
Kenny Root5ab21572011-07-27 11:11:19 -07006526 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
Kenny Root05ca4c92011-09-15 10:36:25 -07006527 + verification.toString() + " with " + pkgLite.verifiers.length
6528 + " optional verifiers");
Kenny Root5ab21572011-07-27 11:11:19 -07006529 }
6530
6531 final int verificationId = mPendingVerificationToken++;
6532
6533 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
6534
6535 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
6536 installerPackageName);
6537
6538 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
6539
rich cannings13d428e2012-09-13 13:43:07 -07006540 verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
6541 pkgLite.packageName);
6542
6543 verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
6544 pkgLite.versionCode);
6545
rich cannings706e8ba2012-08-20 13:20:14 -07006546 if (verificationParams != null) {
6547 if (verificationParams.getVerificationURI() != null) {
6548 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
6549 verificationParams.getVerificationURI());
6550 }
6551 if (verificationParams.getOriginatingURI() != null) {
6552 verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
6553 verificationParams.getOriginatingURI());
6554 }
6555 if (verificationParams.getReferrer() != null) {
6556 verification.putExtra(Intent.EXTRA_REFERRER,
6557 verificationParams.getReferrer());
6558 }
Ben Gruver37d83a32012-09-27 13:02:06 -07006559 if (verificationParams.getOriginatingUid() >= 0) {
6560 verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
6561 verificationParams.getOriginatingUid());
6562 }
rich cannings13d428e2012-09-13 13:43:07 -07006563 if (verificationParams.getInstallerUid() >= 0) {
6564 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
6565 verificationParams.getInstallerUid());
6566 }
Kenny Root5ab21572011-07-27 11:11:19 -07006567 }
6568
Kenny Root05ca4c92011-09-15 10:36:25 -07006569 final PackageVerificationState verificationState = new PackageVerificationState(
6570 requiredUid, args);
6571
6572 mPendingVerification.append(verificationId, verificationState);
6573
6574 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
6575 receivers, verificationState);
Kenny Root5ab21572011-07-27 11:11:19 -07006576
6577 /*
Kenny Root05ca4c92011-09-15 10:36:25 -07006578 * If any sufficient verifiers were listed in the package
6579 * manifest, attempt to ask them.
Kenny Root5ab21572011-07-27 11:11:19 -07006580 */
Kenny Root05ca4c92011-09-15 10:36:25 -07006581 if (sufficientVerifiers != null) {
6582 final int N = sufficientVerifiers.size();
6583 if (N == 0) {
6584 Slog.i(TAG, "Additional verifiers required, but none installed.");
6585 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
6586 } else {
6587 for (int i = 0; i < N; i++) {
6588 final ComponentName verifierComponent = sufficientVerifiers.get(i);
6589
6590 final Intent sufficientIntent = new Intent(verification);
6591 sufficientIntent.setComponent(verifierComponent);
6592
rich canningsd55deb02012-10-02 14:53:08 -07006593 mContext.sendBroadcastAsUser(sufficientIntent, getUser());
Kenny Root05ca4c92011-09-15 10:36:25 -07006594 }
6595 }
6596 }
6597
6598 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
6599 mRequiredVerifierPackage, receivers);
6600 if (ret == PackageManager.INSTALL_SUCCEEDED
6601 && mRequiredVerifierPackage != null) {
6602 /*
6603 * Send the intent to the required verification agent,
6604 * but only start the verification timeout after the
6605 * target BroadcastReceivers have run.
6606 */
6607 verification.setComponent(requiredVerifierComponent);
rich canningsd55deb02012-10-02 14:53:08 -07006608 mContext.sendOrderedBroadcastAsUser(verification, getUser(),
Kenny Root05ca4c92011-09-15 10:36:25 -07006609 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6610 new BroadcastReceiver() {
6611 @Override
6612 public void onReceive(Context context, Intent intent) {
6613 final Message msg = mHandler
6614 .obtainMessage(CHECK_PENDING_VERIFICATION);
6615 msg.arg1 = verificationId;
6616 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
6617 }
6618 }, null, 0, null, null);
6619
6620 /*
6621 * We don't want the copy to proceed until verification
6622 * succeeds, so null out this field.
6623 */
6624 mArgs = null;
6625 }
Kenny Root5ab21572011-07-27 11:11:19 -07006626 } else {
Kenny Root05ca4c92011-09-15 10:36:25 -07006627 /*
6628 * No package verification is enabled, so immediately start
6629 * the remote call to initiate copy using temporary file.
6630 */
Kenny Root5ab21572011-07-27 11:11:19 -07006631 ret = args.copyApk(mContainerService, true);
6632 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006633 }
Kenny Root5ab21572011-07-27 11:11:19 -07006634
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006635 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006636 }
6637
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006638 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006639 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07006640 // If mArgs is null, then MCS couldn't be reached. When it
6641 // reconnects, it will try again to install. At that point, this
6642 // will succeed.
6643 if (mArgs != null) {
6644 processPendingInstall(mArgs, mRet);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006645
Kenny Root0b2fa8c2012-09-14 10:26:16 -07006646 if (mTempPackage != null) {
6647 if (!mTempPackage.delete()) {
6648 Slog.w(TAG, "Couldn't delete temporary file: " +
6649 mTempPackage.getAbsolutePath());
6650 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006651 }
6652 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006653 }
6654
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006655 @Override
6656 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006657 mArgs = createInstallArgs(this);
6658 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006659 }
Kenny Root6dceb882012-04-12 14:23:49 -07006660
6661 public boolean isForwardLocked() {
6662 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6663 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006664
6665 public Uri getPackageUri() {
6666 if (mTempPackage != null) {
6667 return Uri.fromFile(mTempPackage);
6668 } else {
6669 return mPackageURI;
6670 }
6671 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006672 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006673
6674 /*
6675 * Utility class used in movePackage api.
6676 * srcArgs and targetArgs are not set for invalid flags and make
6677 * sure to do null checks when invoking methods on them.
6678 * We probably want to return ErrorPrams for both failed installs
6679 * and moves.
6680 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006681 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006682 final IPackageMoveObserver observer;
6683 final int flags;
6684 final String packageName;
6685 final InstallArgs srcArgs;
6686 final InstallArgs targetArgs;
Kenny Root6dceb882012-04-12 14:23:49 -07006687 int uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006688 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07006689
6690 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
Amith Yamasani6ec10122012-08-23 13:49:25 -07006691 String packageName, String dataDir, int uid, UserHandle user) {
6692 super(user);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006693 this.srcArgs = srcArgs;
6694 this.observer = observer;
6695 this.flags = flags;
6696 this.packageName = packageName;
Kenny Root6dceb882012-04-12 14:23:49 -07006697 this.uid = uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006698 if (srcArgs != null) {
6699 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07006700 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006701 } else {
6702 targetArgs = null;
6703 }
6704 }
6705
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006706 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006707 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6708 // Check for storage space on target medium
6709 if (!targetArgs.checkFreeStorage(mContainerService)) {
6710 Log.w(TAG, "Insufficient storage to install");
6711 return;
6712 }
Kenny Rootbf023582012-05-02 16:56:15 -07006713
6714 mRet = srcArgs.doPreCopy();
6715 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6716 return;
6717 }
6718
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006719 mRet = targetArgs.copyApk(mContainerService, false);
Kenny Rootbf023582012-05-02 16:56:15 -07006720 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6721 srcArgs.doPostCopy(uid);
6722 return;
6723 }
6724
6725 mRet = srcArgs.doPostCopy(uid);
6726 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6727 return;
6728 }
6729
6730 mRet = targetArgs.doPreInstall(mRet);
6731 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6732 return;
6733 }
6734
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006735 if (DEBUG_SD_INSTALL) {
6736 StringBuilder builder = new StringBuilder();
6737 if (srcArgs != null) {
6738 builder.append("src: ");
6739 builder.append(srcArgs.getCodePath());
6740 }
6741 if (targetArgs != null) {
6742 builder.append(" target : ");
6743 builder.append(targetArgs.getCodePath());
6744 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006745 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006746 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006747 }
6748
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006749 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006750 void handleReturnCode() {
Kenny Root6dceb882012-04-12 14:23:49 -07006751 targetArgs.doPostInstall(mRet, uid);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006752 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
6753 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
6754 currentStatus = PackageManager.MOVE_SUCCEEDED;
6755 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
6756 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
6757 }
6758 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006759 }
6760
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006761 @Override
6762 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006763 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006764 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006765 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006766
Kenny Root6dceb882012-04-12 14:23:49 -07006767 /**
6768 * Used during creation of InstallArgs
6769 *
6770 * @param flags package installation flags
6771 * @return true if should be installed on external storage
6772 */
6773 private static boolean installOnSd(int flags) {
6774 if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
6775 return false;
6776 }
6777 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
6778 return true;
6779 }
6780 return false;
6781 }
6782
6783 /**
6784 * Used during creation of InstallArgs
6785 *
6786 * @param flags package installation flags
6787 * @return true if should be installed as forward locked
6788 */
6789 private static boolean installForwardLocked(int flags) {
6790 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6791 }
6792
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006793 private InstallArgs createInstallArgs(InstallParams params) {
Kenny Root6dceb882012-04-12 14:23:49 -07006794 if (installOnSd(params.flags) || params.isForwardLocked()) {
6795 return new AsecInstallArgs(params);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006796 } else {
6797 return new FileInstallArgs(params);
6798 }
6799 }
6800
Kenny Root85387d72010-08-26 10:13:11 -07006801 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
6802 String nativeLibraryPath) {
Kenny Root84e35ea2012-06-06 16:05:05 -07006803 final boolean isInAsec;
6804 if (installOnSd(flags)) {
6805 /* Apps on SD card are always in ASEC containers. */
6806 isInAsec = true;
6807 } else if (installForwardLocked(flags)
6808 && !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
6809 /*
6810 * Forward-locked apps are only in ASEC containers if they're the
6811 * new style
6812 */
6813 isInAsec = true;
6814 } else {
6815 isInAsec = false;
6816 }
6817
6818 if (isInAsec) {
Kenny Root6dceb882012-04-12 14:23:49 -07006819 return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07006820 installOnSd(flags), installForwardLocked(flags));
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006821 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006822 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006823 }
6824 }
6825
Kenny Root85387d72010-08-26 10:13:11 -07006826 // Used by package mover
6827 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Kenny Root6dceb882012-04-12 14:23:49 -07006828 if (installOnSd(flags) || installForwardLocked(flags)) {
Kenny Rootbf023582012-05-02 16:56:15 -07006829 String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
6830 + AsecInstallArgs.RES_FILE_NAME);
6831 return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
6832 installForwardLocked(flags));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006833 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006834 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006835 }
6836 }
6837
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006838 static abstract class InstallArgs {
6839 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006840 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006841 final int flags;
6842 final Uri packageURI;
6843 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07006844 final ManifestDigest manifestDigest;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006845 final UserHandle user;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006846
Kenny Root5ab21572011-07-27 11:11:19 -07006847 InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006848 String installerPackageName, ManifestDigest manifestDigest,
6849 UserHandle user) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006850 this.packageURI = packageURI;
6851 this.flags = flags;
6852 this.observer = observer;
6853 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07006854 this.manifestDigest = manifestDigest;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006855 this.user = user;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006856 }
6857
6858 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006859 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006860 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006861 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Kenny Root6dceb882012-04-12 14:23:49 -07006862
6863 abstract int doPostInstall(int status, int uid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006864 abstract String getCodePath();
6865 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07006866 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006867 // Need installer lock especially for dex file removal.
6868 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006869 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006870 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Kenny Root6dceb882012-04-12 14:23:49 -07006871
Kenny Rootbf023582012-05-02 16:56:15 -07006872 /**
6873 * Called before the source arguments are copied. This is used mostly
6874 * for MoveParams when it needs to read the source file to put it in the
6875 * destination.
6876 */
6877 int doPreCopy() {
6878 return PackageManager.INSTALL_SUCCEEDED;
6879 }
6880
6881 /**
6882 * Called after the source arguments are copied. This is used mostly for
6883 * MoveParams when it needs to read the source file to put it in the
6884 * destination.
6885 *
6886 * @return
6887 */
6888 int doPostCopy(int uid) {
6889 return PackageManager.INSTALL_SUCCEEDED;
6890 }
6891
Kenny Root6dceb882012-04-12 14:23:49 -07006892 protected boolean isFwdLocked() {
6893 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6894 }
rich canningsd55deb02012-10-02 14:53:08 -07006895
6896 UserHandle getUser() {
6897 return user;
6898 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006899 }
6900
6901 class FileInstallArgs extends InstallArgs {
6902 File installDir;
6903 String codeFileName;
6904 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07006905 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006906 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006907
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006908 FileInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006909 super(params.getPackageUri(), params.observer, params.flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006910 params.installerPackageName, params.getManifestDigest(),
6911 params.getUser());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006912 }
6913
Kenny Root85387d72010-08-26 10:13:11 -07006914 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006915 super(null, null, 0, null, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006916 File codeFile = new File(fullCodePath);
6917 installDir = codeFile.getParentFile();
6918 codeFileName = fullCodePath;
6919 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006920 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006921 }
6922
Kenny Root85387d72010-08-26 10:13:11 -07006923 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006924 super(packageURI, null, 0, null, null, null);
Kenny Root85387d72010-08-26 10:13:11 -07006925 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006926 String apkName = getNextCodePath(null, pkgName, ".apk");
6927 codeFileName = new File(installDir, apkName + ".apk").getPath();
6928 resourceFileName = getResourcePathFromCodePath();
Kenny Rootddbe50d2012-09-06 13:18:37 -07006929 libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006930 }
6931
Kenny Root11128572010-10-11 10:51:32 -07006932 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07006933 final long lowThreshold;
6934
6935 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
6936 .getService(DeviceStorageMonitorService.SERVICE);
6937 if (dsm == null) {
6938 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
6939 lowThreshold = 0L;
6940 } else {
6941 if (dsm.isMemoryLow()) {
6942 Log.w(TAG, "Memory is reported as being too low; aborting package install");
6943 return false;
6944 }
6945
6946 lowThreshold = dsm.getMemoryLowThreshold();
6947 }
6948
Kenny Root11128572010-10-11 10:51:32 -07006949 try {
6950 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6951 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006952 return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07006953 } finally {
6954 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6955 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006956 }
6957
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006958 String getCodePath() {
6959 return codeFileName;
6960 }
6961
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006962 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07006963 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006964 codeFileName = createTempPackageFile(installDir).getPath();
6965 resourceFileName = getResourcePathFromCodePath();
Kenny Rootddbe50d2012-09-06 13:18:37 -07006966 libraryPath = getLibraryPathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006967 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006968 }
6969
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006970 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006971 if (temp) {
6972 // Generate temp file name
6973 createCopyFile();
6974 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006975 // Get a ParcelFileDescriptor to write to the output file
6976 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006977 if (!created) {
6978 try {
6979 codeFile.createNewFile();
6980 // Set permissions
6981 if (!setPermissions()) {
6982 // Failed setting permissions.
6983 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6984 }
6985 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006986 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006987 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6988 }
6989 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006990 ParcelFileDescriptor out = null;
6991 try {
Kenny Root85387d72010-08-26 10:13:11 -07006992 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006993 } catch (FileNotFoundException e) {
Kenny Rootf5121a92011-08-10 16:23:32 -07006994 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006995 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6996 }
6997 // Copy the resource now
6998 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6999 try {
Kenny Root11128572010-10-11 10:51:32 -07007000 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
7001 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007002 ret = imcs.copyResource(packageURI, null, out);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007003 } finally {
Kenny Root2782a472012-04-14 21:48:21 -07007004 IoUtils.closeQuietly(out);
Kenny Root11128572010-10-11 10:51:32 -07007005 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007006 }
Kenny Root85387d72010-08-26 10:13:11 -07007007
Kenny Root2782a472012-04-14 21:48:21 -07007008 if (isFwdLocked()) {
7009 final File destResourceFile = new File(getResourcePath());
7010
7011 // Copy the public files
7012 try {
7013 PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
7014 } catch (IOException e) {
7015 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
7016 + " forward-locked app.");
7017 destResourceFile.delete();
7018 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7019 }
7020 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07007021
7022 final File nativeLibraryFile = new File(getNativeLibraryPath());
7023 Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
7024 if (nativeLibraryFile.exists()) {
7025 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
7026 nativeLibraryFile.delete();
7027 }
7028 try {
7029 int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
7030 if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
7031 return copyRet;
7032 }
7033 } catch (IOException e) {
7034 Slog.e(TAG, "Copying native libraries failed", e);
7035 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
7036 }
7037
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007038 return ret;
7039 }
7040
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007041 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007042 if (status != PackageManager.INSTALL_SUCCEEDED) {
7043 cleanUp();
7044 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007045 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007046 }
7047
7048 boolean doRename(int status, final String pkgName, String oldCodePath) {
7049 if (status != PackageManager.INSTALL_SUCCEEDED) {
7050 cleanUp();
7051 return false;
7052 } else {
Kenny Root2782a472012-04-14 21:48:21 -07007053 final File oldCodeFile = new File(getCodePath());
7054 final File oldResourceFile = new File(getResourcePath());
Kenny Rootddbe50d2012-09-06 13:18:37 -07007055 final File oldLibraryFile = new File(getNativeLibraryPath());
Kenny Root2782a472012-04-14 21:48:21 -07007056
7057 // Rename APK file based on packageName
7058 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
7059 final File newCodeFile = new File(installDir, apkName + ".apk");
7060 if (!oldCodeFile.renameTo(newCodeFile)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007061 return false;
7062 }
Kenny Root2782a472012-04-14 21:48:21 -07007063 codeFileName = newCodeFile.getPath();
7064
7065 // Rename public resource file if it's forward-locked.
7066 final File newResFile = new File(getResourcePathFromCodePath());
7067 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
7068 return false;
7069 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07007070 resourceFileName = newResFile.getPath();
7071
7072 // Rename library path
7073 final File newLibraryFile = new File(getLibraryPathFromCodePath());
7074 if (newLibraryFile.exists()) {
7075 NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
7076 newLibraryFile.delete();
7077 }
7078 if (!oldLibraryFile.renameTo(newLibraryFile)) {
7079 Slog.e(TAG, "Cannot rename native library directory "
7080 + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
7081 return false;
7082 }
7083 libraryPath = newLibraryFile.getPath();
Kenny Root2782a472012-04-14 21:48:21 -07007084
7085 // Attempt to set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007086 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007087 return false;
7088 }
Kenny Root2782a472012-04-14 21:48:21 -07007089
rpcraig554cb0c2012-07-05 06:41:43 -04007090 if (!SELinux.restorecon(newCodeFile)) {
7091 return false;
7092 }
7093
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007094 return true;
7095 }
7096 }
7097
Kenny Root6dceb882012-04-12 14:23:49 -07007098 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007099 if (status != PackageManager.INSTALL_SUCCEEDED) {
7100 cleanUp();
7101 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007102 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007103 }
7104
7105 String getResourcePath() {
7106 return resourceFileName;
7107 }
7108
Kenny Root2782a472012-04-14 21:48:21 -07007109 private String getResourcePathFromCodePath() {
7110 final String codePath = getCodePath();
7111 if (isFwdLocked()) {
7112 final StringBuilder sb = new StringBuilder();
7113
7114 sb.append(mAppInstallDir.getPath());
7115 sb.append('/');
7116 sb.append(getApkName(codePath));
7117 sb.append(".zip");
7118
7119 /*
7120 * If our APK is a temporary file, mark the resource as a
7121 * temporary file as well so it can be cleaned up after
7122 * catastrophic failure.
7123 */
7124 if (codePath.endsWith(".tmp")) {
7125 sb.append(".tmp");
7126 }
7127
7128 return sb.toString();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007129 } else {
7130 return codePath;
7131 }
7132 }
7133
Kenny Rootddbe50d2012-09-06 13:18:37 -07007134 private String getLibraryPathFromCodePath() {
7135 return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
7136 }
7137
Kenny Root85387d72010-08-26 10:13:11 -07007138 @Override
7139 String getNativeLibraryPath() {
Kenny Rootddbe50d2012-09-06 13:18:37 -07007140 if (libraryPath == null) {
7141 libraryPath = getLibraryPathFromCodePath();
7142 }
Kenny Root85387d72010-08-26 10:13:11 -07007143 return libraryPath;
7144 }
7145
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007146 private boolean cleanUp() {
7147 boolean ret = true;
7148 String sourceDir = getCodePath();
7149 String publicSourceDir = getResourcePath();
7150 if (sourceDir != null) {
7151 File sourceFile = new File(sourceDir);
7152 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007153 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007154 ret = false;
7155 }
7156 // Delete application's code and resources
7157 sourceFile.delete();
7158 }
7159 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
7160 final File publicSourceFile = new File(publicSourceDir);
7161 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007162 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007163 }
7164 if (publicSourceFile.exists()) {
7165 publicSourceFile.delete();
7166 }
7167 }
Kenny Rootddbe50d2012-09-06 13:18:37 -07007168
7169 if (libraryPath != null) {
7170 File nativeLibraryFile = new File(libraryPath);
7171 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
7172 if (!nativeLibraryFile.delete()) {
7173 Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
7174 }
7175 }
7176
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007177 return ret;
7178 }
7179
7180 void cleanUpResourcesLI() {
7181 String sourceDir = getCodePath();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007182 if (cleanUp()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007183 int retCode = mInstaller.rmdex(sourceDir);
7184 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007185 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007186 + " at location "
7187 + sourceDir + ", retcode=" + retCode);
7188 // we don't consider this to be a failure of the core package deletion
7189 }
7190 }
7191 }
7192
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007193 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007194 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07007195 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007196 final int filePermissions =
7197 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
7198 |FileUtils.S_IROTH;
7199 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
7200 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007201 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007202 getCodePath()
7203 + ". The return code was: " + retCode);
7204 // TODO Define new internal error
7205 return false;
7206 }
7207 return true;
7208 }
7209 return true;
7210 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007211
7212 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07007213 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007214 cleanUpResourcesLI();
7215 return true;
7216 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007217 }
7218
Kenny Root51a573c2012-05-17 13:30:28 -07007219 private boolean isAsecExternal(String cid) {
7220 final String asecPath = PackageHelper.getSdFilesystem(cid);
7221 return !asecPath.startsWith(mAsecInternalPath);
7222 }
7223
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007224 /**
7225 * Extract the MountService "container ID" from the full code path of an
7226 * .apk.
7227 */
7228 static String cidFromCodePath(String fullCodePath) {
7229 int eidx = fullCodePath.lastIndexOf("/");
7230 String subStr1 = fullCodePath.substring(0, eidx);
7231 int sidx = subStr1.lastIndexOf("/");
7232 return subStr1.substring(sidx+1, eidx);
7233 }
7234
Kenny Root6dceb882012-04-12 14:23:49 -07007235 class AsecInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007236 static final String RES_FILE_NAME = "pkg.apk";
Kenny Root6dceb882012-04-12 14:23:49 -07007237 static final String PUBLIC_RES_FILE_NAME = "res.zip";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007238
Kenny Root85387d72010-08-26 10:13:11 -07007239 String cid;
7240 String packagePath;
Kenny Root6dceb882012-04-12 14:23:49 -07007241 String resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07007242 String libraryPath;
7243
Kenny Root6dceb882012-04-12 14:23:49 -07007244 AsecInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07007245 super(params.getPackageUri(), params.observer, params.flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007246 params.installerPackageName, params.getManifestDigest(),
7247 params.getUser());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007248 }
7249
Kenny Root6dceb882012-04-12 14:23:49 -07007250 AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07007251 boolean isExternal, boolean isForwardLocked) {
7252 super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007253 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
7254 null, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007255 // Extract cid from fullCodePath
7256 int eidx = fullCodePath.lastIndexOf("/");
7257 String subStr1 = fullCodePath.substring(0, eidx);
7258 int sidx = subStr1.lastIndexOf("/");
7259 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07007260 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007261 }
7262
Kenny Rootc7a89992012-06-05 15:13:17 -07007263 AsecInstallArgs(String cid, boolean isForwardLocked) {
7264 super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007265 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
7266 null, null, null);
Dianne Hackbornaa77de12010-05-14 22:33:54 -07007267 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07007268 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007269 }
7270
Kenny Rootbf023582012-05-02 16:56:15 -07007271 AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
7272 super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007273 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
7274 null, null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007275 this.cid = cid;
7276 }
7277
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007278 void createCopyFile() {
7279 cid = getTempContainerId();
7280 }
7281
Kenny Root11128572010-10-11 10:51:32 -07007282 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
7283 try {
7284 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
7285 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07007286 return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07007287 } finally {
7288 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
7289 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08007290 }
7291
Kenny Root6dceb882012-04-12 14:23:49 -07007292 private final boolean isExternal() {
7293 return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
7294 }
7295
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007296 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007297 if (temp) {
7298 createCopyFile();
Kenny Rootf5121a92011-08-10 16:23:32 -07007299 } else {
7300 /*
7301 * Pre-emptively destroy the container since it's destroyed if
7302 * copying fails due to it existing anyway.
7303 */
7304 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007305 }
Kenny Root11128572010-10-11 10:51:32 -07007306
7307 final String newCachePath;
7308 try {
7309 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
7310 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07007311 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
7312 RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07007313 } finally {
7314 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
7315 }
7316
Kenny Root85387d72010-08-26 10:13:11 -07007317 if (newCachePath != null) {
7318 setCachePath(newCachePath);
7319 return PackageManager.INSTALL_SUCCEEDED;
7320 } else {
7321 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
7322 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007323 }
7324
7325 @Override
7326 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07007327 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007328 }
7329
7330 @Override
7331 String getResourcePath() {
Kenny Root6dceb882012-04-12 14:23:49 -07007332 return resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07007333 }
7334
7335 @Override
7336 String getNativeLibraryPath() {
7337 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007338 }
7339
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007340 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007341 if (status != PackageManager.INSTALL_SUCCEEDED) {
7342 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08007343 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007344 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08007345 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007346 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07007347 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
7348 Process.SYSTEM_UID);
7349 if (newCachePath != null) {
7350 setCachePath(newCachePath);
7351 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007352 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
7353 }
7354 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007355 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007356 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007357 }
7358
7359 boolean doRename(int status, final String pkgName,
7360 String oldCodePath) {
7361 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007362 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007363 if (PackageHelper.isContainerMounted(cid)) {
7364 // Unmount the container
7365 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007366 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007367 return false;
7368 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007369 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007370 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07007371 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
7372 " which might be stale. Will try to clean up.");
7373 // Clean up the stale container and proceed to recreate.
7374 if (!PackageHelper.destroySdDir(newCacheId)) {
7375 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
7376 return false;
7377 }
7378 // Successfully cleaned up stale container. Try to rename again.
7379 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
7380 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
7381 + " inspite of cleaning it up.");
7382 return false;
7383 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007384 }
7385 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007386 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007387 newCachePath = PackageHelper.mountSdDir(newCacheId,
7388 getEncryptKey(), Process.SYSTEM_UID);
7389 } else {
7390 newCachePath = PackageHelper.getSdDir(newCacheId);
7391 }
7392 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007393 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007394 return false;
7395 }
7396 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07007397 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007398 " at new path: " + newCachePath);
7399 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07007400 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007401 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007402 }
7403
Kenny Root85387d72010-08-26 10:13:11 -07007404 private void setCachePath(String newCachePath) {
7405 File cachePath = new File(newCachePath);
7406 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
7407 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
Kenny Root6dceb882012-04-12 14:23:49 -07007408
7409 if (isFwdLocked()) {
7410 resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
7411 } else {
7412 resourcePath = packagePath;
7413 }
Kenny Root85387d72010-08-26 10:13:11 -07007414 }
7415
Kenny Root6dceb882012-04-12 14:23:49 -07007416 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007417 if (status != PackageManager.INSTALL_SUCCEEDED) {
7418 cleanUp();
7419 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07007420 final int groupOwner;
7421 final String protectedFile;
7422 if (isFwdLocked()) {
Kenny Roote091f222012-09-11 15:01:26 -07007423 groupOwner = UserHandle.getSharedAppGid(uid);
Kenny Rootbf023582012-05-02 16:56:15 -07007424 protectedFile = RES_FILE_NAME;
7425 } else {
7426 groupOwner = -1;
7427 protectedFile = null;
7428 }
7429
Kenny Root6dceb882012-04-12 14:23:49 -07007430 if (uid < Process.FIRST_APPLICATION_UID
Kenny Rootbf023582012-05-02 16:56:15 -07007431 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Kenny Root6dceb882012-04-12 14:23:49 -07007432 Slog.e(TAG, "Failed to finalize " + cid);
7433 PackageHelper.destroySdDir(cid);
7434 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
7435 }
7436
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08007437 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007438 if (!mounted) {
Kenny Root6dceb882012-04-12 14:23:49 -07007439 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007440 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007441 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007442 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007443 }
7444
7445 private void cleanUp() {
Kenny Root6dceb882012-04-12 14:23:49 -07007446 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
7447
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007448 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08007449 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007450 }
7451
7452 void cleanUpResourcesLI() {
7453 String sourceFile = getCodePath();
7454 // Remove dex file
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007455 int retCode = mInstaller.rmdex(sourceFile);
7456 if (retCode < 0) {
7457 Slog.w(TAG, "Couldn't remove dex file for package: "
7458 + " at location "
7459 + sourceFile.toString() + ", retcode=" + retCode);
7460 // we don't consider this to be a failure of the core package deletion
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007461 }
7462 cleanUp();
7463 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007464
7465 boolean matchContainer(String app) {
7466 if (cid.startsWith(app)) {
7467 return true;
7468 }
7469 return false;
7470 }
7471
7472 String getPackageName() {
Kenny Rootc7a89992012-06-05 15:13:17 -07007473 return getAsecPackageName(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007474 }
7475
7476 boolean doPostDeleteLI(boolean delete) {
7477 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08007478 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007479 if (mounted) {
7480 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08007481 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007482 }
7483 if (ret && delete) {
7484 cleanUpResourcesLI();
7485 }
7486 return ret;
7487 }
Kenny Rootbf023582012-05-02 16:56:15 -07007488
7489 @Override
7490 int doPreCopy() {
7491 if (isFwdLocked()) {
7492 if (!PackageHelper.fixSdPermissions(cid,
7493 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
7494 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
7495 }
7496 }
7497
7498 return PackageManager.INSTALL_SUCCEEDED;
7499 }
7500
7501 @Override
7502 int doPostCopy(int uid) {
7503 if (isFwdLocked()) {
Kenny Rootbf023582012-05-02 16:56:15 -07007504 if (uid < Process.FIRST_APPLICATION_UID
Kenny Roote091f222012-09-11 15:01:26 -07007505 || !PackageHelper.fixSdPermissions(cid, UserHandle.getSharedAppGid(uid),
7506 RES_FILE_NAME)) {
Kenny Rootbf023582012-05-02 16:56:15 -07007507 Slog.e(TAG, "Failed to finalize " + cid);
7508 PackageHelper.destroySdDir(cid);
7509 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
7510 }
7511 }
7512
7513 return PackageManager.INSTALL_SUCCEEDED;
7514 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007515 };
7516
Kenny Rootc7a89992012-06-05 15:13:17 -07007517 static String getAsecPackageName(String packageCid) {
7518 int idx = packageCid.lastIndexOf("-");
7519 if (idx == -1) {
7520 return packageCid;
7521 }
7522 return packageCid.substring(0, idx);
7523 }
7524
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007525 // Utility method used to create code paths based on package name and available index.
7526 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
7527 String idxStr = "";
7528 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007529 // Fall back to default value of idx=1 if prefix is not
7530 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007531 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00007532 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007533 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00007534 if (subStr.endsWith(suffix)) {
7535 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007536 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007537 // If oldCodePath already contains prefix find out the
7538 // ending index to either increment or decrement.
7539 int sidx = subStr.lastIndexOf(prefix);
7540 if (sidx != -1) {
7541 subStr = subStr.substring(sidx + prefix.length());
7542 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007543 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
7544 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007545 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007546 try {
7547 idx = Integer.parseInt(subStr);
7548 if (idx <= 1) {
7549 idx++;
7550 } else {
7551 idx--;
7552 }
7553 } catch(NumberFormatException e) {
7554 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007555 }
7556 }
7557 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007558 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007559 return prefix + idxStr;
7560 }
7561
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007562 // Utility method used to ignore ADD/REMOVE events
7563 // by directory observer.
7564 private static boolean ignoreCodePath(String fullPathStr) {
7565 String apkName = getApkName(fullPathStr);
7566 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
7567 if (idx != -1 && ((idx+1) < apkName.length())) {
7568 // Make sure the package ends with a numeral
7569 String version = apkName.substring(idx+1);
7570 try {
7571 Integer.parseInt(version);
7572 return true;
7573 } catch (NumberFormatException e) {}
7574 }
7575 return false;
7576 }
7577
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007578 // Utility method that returns the relative package path with respect
7579 // to the installation directory. Like say for /data/data/com.test-1.apk
7580 // string com.test-1 is returned.
7581 static String getApkName(String codePath) {
7582 if (codePath == null) {
7583 return null;
7584 }
7585 int sidx = codePath.lastIndexOf("/");
7586 int eidx = codePath.lastIndexOf(".");
7587 if (eidx == -1) {
7588 eidx = codePath.length();
7589 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007590 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007591 return null;
7592 }
7593 return codePath.substring(sidx+1, eidx);
7594 }
7595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 class PackageInstalledInfo {
7597 String name;
7598 int uid;
Dianne Hackborn786b4402012-08-27 15:14:02 -07007599 // The set of users that originally had this package installed.
7600 int[] origUsers;
7601 // The set of users that now have this package installed.
7602 int[] newUsers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 PackageParser.Package pkg;
7604 int returnCode;
7605 PackageRemovedInfo removedInfo;
7606 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 /*
7609 * Install a non-existing package.
7610 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007611 private void installNewPackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007612 int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02007613 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007615 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08007616
Dave Burke383fa182012-10-23 23:12:19 -07007617 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07007619 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
7620 // A package with the same name is already installed, though
7621 // it has been renamed to an older name. The package we
7622 // are trying to install should be installed as an update to
7623 // the existing one, but that has not been requested, so bail.
7624 Slog.w(TAG, "Attempt to re-install " + pkgName
7625 + " without first uninstalling package running as "
7626 + mSettings.mRenamedPackages.get(pkgName));
7627 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
7628 return;
7629 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007630 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007632 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 + " without first uninstalling.");
7634 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
7635 return;
7636 }
7637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007638 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007639 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007640 System.currentTimeMillis(), user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007642 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7644 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
7645 }
7646 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007647 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007648 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007649 res);
7650 // delete the partially installed application. the data directory will have to be
7651 // restored if it was already existing
7652 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
7653 // remove package from internal structures. Note that we want deletePackageX to
7654 // delete the package data and cache directories that it created in
7655 // scanPackageLocked, unless those directories existed before we even tried to
7656 // install.
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007657 deletePackageLI(pkgName, UserHandle.ALL, false,
7658 dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007659 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 }
7661 }
7662 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007663
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007664 private void replacePackageLI(PackageParser.Package pkg,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007665 int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02007666 String installerPackageName, PackageInstalledInfo res) {
7667
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007668 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007669 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 // First find the old package info and check signatures
7671 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007672 oldPackage = mPackages.get(pkgName);
Kenny Root447106f2011-03-23 11:00:15 -07007673 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07007674 != PackageManager.SIGNATURE_MATCH) {
Kenny Root8c11f1d2012-04-14 12:10:38 -07007675 Slog.w(TAG, "New package has a different signature: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
7677 return;
7678 }
7679 }
Kenny Root85387d72010-08-26 10:13:11 -07007680 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007681 if (sysPkg) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007682 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
7683 user, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 } else {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007685 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
7686 user, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 }
7688 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007691 PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02007692 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 PackageParser.Package newPackage = null;
7694 String pkgName = deletedPackage.packageName;
7695 boolean deletedPkg = true;
7696 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007697
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007698 long origUpdateTime;
7699 if (pkg.mExtras != null) {
7700 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
7701 } else {
7702 origUpdateTime = 0;
7703 }
7704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 // First delete the existing package while retaining the data directory
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007706 if (!deletePackageLI(pkgName, null, true, PackageManager.DELETE_KEEP_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007707 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007708 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
7710 deletedPkg = false;
7711 } else {
7712 // Successfully deleted the old package. Now proceed with re-installation
7713 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007714 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007715 System.currentTimeMillis(), user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007717 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7719 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08007720 }
7721 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007722 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007723 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007724 res);
7725 updatedSettings = true;
7726 }
7727 }
7728
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007729 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 // remove package from internal structures. Note that we want deletePackageX to
7731 // delete the package data and cache directories that it created in
7732 // scanPackageLocked, unless those directories existed before we even tried to
7733 // install.
7734 if(updatedSettings) {
7735 deletePackageLI(
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007736 pkgName, null, true,
7737 PackageManager.DELETE_KEEP_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007738 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 }
7740 // Since we failed to install the new package we need to restore the old
7741 // package that we deleted.
7742 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007743 File restoreFile = new File(deletedPackage.mPath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007744 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007745 boolean oldOnSd = isExternal(deletedPackage);
7746 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
7747 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
7748 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007749 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
7750 | SCAN_UPDATE_TIME;
7751 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
Dianne Hackborn786b4402012-08-27 15:14:02 -07007752 origUpdateTime, null) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007753 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
7754 return;
7755 }
7756 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07007757 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007758 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007759 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08007760 UPDATE_PERMISSIONS_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07007761 // can downgrade to reader
7762 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007763 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007764 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765 }
7766 }
7767 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007770 PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
Jacek Surazski65e13172009-04-28 15:26:38 +02007771 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 PackageParser.Package newPackage = null;
7773 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007774 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007775 PackageParser.PARSE_IS_SYSTEM;
7776 String packageName = deletedPackage.packageName;
7777 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
7778 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007779 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007780 return;
7781 }
7782 PackageParser.Package oldPkg;
7783 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07007784 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 synchronized (mPackages) {
7786 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007787 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007788 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
7789 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007790 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 return;
7792 }
7793 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007794
7795 killApplication(packageName, oldPkg.applicationInfo.uid);
7796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 res.removedInfo.uid = oldPkg.applicationInfo.uid;
7798 res.removedInfo.removedPackage = packageName;
7799 // Remove existing system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07007800 removePackageLI(oldPkgSetting, true);
Kenny Root447106f2011-03-23 11:00:15 -07007801 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08007802 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007803 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007804 // We didn't need to disable the .apk as a current system package,
7805 // which means we are replacing another update that is already
7806 // installed. We need to make sure to delete the older one's .apk.
Kenny Root6dceb882012-04-12 14:23:49 -07007807 res.removedInfo.args = createInstallArgs(0,
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007808 deletedPackage.applicationInfo.sourceDir,
7809 deletedPackage.applicationInfo.publicSourceDir,
7810 deletedPackage.applicationInfo.nativeLibraryDir);
7811 } else {
7812 res.removedInfo.args = null;
7813 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08007814 }
7815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 // Successfully disabled the old package. Now proceed with re-installation
7817 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
7818 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007819 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007821 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007822 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7823 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
7824 }
7825 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007826 if (newPackage.mExtras != null) {
7827 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
7828 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
7829 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
7830 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007831 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 updatedSettings = true;
7833 }
7834
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007835 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 // Re installation failed. Restore old information
7837 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07007838 if (newPackage != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07007839 removeInstalledPackageLI(newPackage, true);
Dianne Hackborn62da8462009-05-13 15:06:13 -07007840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 // Add back the old system package
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007842 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 // Restore the old system information in Settings
7844 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007845 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07007846 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02007847 mSettings.setInstallerPackageName(packageName,
7848 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007849 }
Kenny Root447106f2011-03-23 11:00:15 -07007850 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 }
7852 }
7853 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007854
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007855 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007856 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007857 int retCode;
7858 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
7859 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
7860 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07007861 if (mNoDexOpt) {
7862 /*
7863 * If we're in an engineering build, programs are lazily run
7864 * through dexopt. If the .dex file doesn't exist yet, it
7865 * will be created when the program is run next.
7866 */
7867 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
7868 } else {
7869 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
7870 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7871 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007872 }
7873 }
7874 return PackageManager.INSTALL_SUCCEEDED;
7875 }
7876
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007877 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007878 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007879 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 synchronized (mPackages) {
7881 //write settings. the installStatus will be incomplete at this stage.
7882 //note that the new package setting would have already been
7883 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07007884 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07007885 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 }
7887
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007888 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007889 != PackageManager.INSTALL_SUCCEEDED) {
7890 // Discontinue if moving dex files failed.
7891 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
Kenny Root6dceb882012-04-12 14:23:49 -07007893
7894 Log.d(TAG, "New package installed in " + newPackage.mPath);
7895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007897 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08007898 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
7899 ? UPDATE_PERMISSIONS_ALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 res.name = pkgName;
7901 res.uid = newPackage.applicationInfo.uid;
7902 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07007903 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02007904 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
7906 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07007907 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 }
7909 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007910
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007911 private void installPackageLI(InstallArgs args,
7912 boolean newInstall, PackageInstalledInfo res) {
7913 int pFlags = args.flags;
7914 String installerPackageName = args.installerPackageName;
7915 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007916 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007917 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007918 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007919 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007920 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007921 // Result object to be returned
7922 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
7923
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007924 // Retrieve PackageSettings and parse package
Kenny Root6dceb882012-04-12 14:23:49 -07007925 int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
7926 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
7927 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007928 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
7929 pp.setSeparateProcesses(mSeparateProcesses);
7930 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
7931 null, mMetrics, parseFlags);
7932 if (pkg == null) {
7933 res.returnCode = pp.getParseError();
7934 return;
7935 }
7936 String pkgName = res.name = pkg.packageName;
7937 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
7938 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
7939 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
7940 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007942 }
7943 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
7944 res.returnCode = pp.getParseError();
7945 return;
7946 }
Kenny Root5ab21572011-07-27 11:11:19 -07007947
7948 /* If the installer passed in a manifest digest, compare it now. */
7949 if (args.manifestDigest != null) {
7950 if (DEBUG_INSTALL) {
7951 final String parsedManifest = pkg.manifestDigest == null ? "null"
7952 : pkg.manifestDigest.toString();
7953 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
7954 + parsedManifest);
7955 }
7956
7957 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
7958 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
7959 return;
7960 }
7961 } else if (DEBUG_INSTALL) {
7962 final String parsedManifest = pkg.manifestDigest == null
7963 ? "null" : pkg.manifestDigest.toString();
7964 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
7965 }
7966
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007967 // Get rid of all references to package scan path via parser.
7968 pp = null;
7969 String oldCodePath = null;
7970 boolean systemApp = false;
7971 synchronized (mPackages) {
7972 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007973 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
7974 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08007975 if (pkg.mOriginalPackages != null
7976 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007977 && mPackages.containsKey(oldName)) {
7978 // This package is derived from an original package,
7979 // and this device has been updating from that original
7980 // name. We must continue using the original name, so
7981 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08007982 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007983 pkgName = pkg.packageName;
7984 replace = true;
7985 } else if (mPackages.containsKey(pkgName)) {
7986 // This package, under its official name, already exists
7987 // on the device; we should replace it.
7988 replace = true;
7989 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007990 }
7991 PackageSetting ps = mSettings.mPackages.get(pkgName);
7992 if (ps != null) {
7993 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
7994 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
7995 systemApp = (ps.pkg.applicationInfo.flags &
7996 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07007997 }
Dianne Hackborn786b4402012-08-27 15:14:02 -07007998 res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
Dianne Hackbornade3eca2009-05-11 18:54:45 -07007999 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008000 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008001
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008002 if (systemApp && onSd) {
8003 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008004 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008005 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
8006 return;
8007 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008008
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008009 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
8010 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
8011 return;
8012 }
8013 // Set application objects path explicitly after the rename
8014 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07008015 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008016 if (replace) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008017 replacePackageLI(pkg, parseFlags, scanMode, args.user,
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008018 installerPackageName, res);
8019 } else {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008020 installNewPackageLI(pkg, parseFlags, scanMode, args.user,
Dianne Hackborn786b4402012-08-27 15:14:02 -07008021 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008023 synchronized (mPackages) {
Dianne Hackborn786b4402012-08-27 15:14:02 -07008024 final PackageSetting ps = mSettings.mPackages.get(pkgName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008025 if (ps != null) {
Dianne Hackborn786b4402012-08-27 15:14:02 -07008026 res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008027 }
8028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008029 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008030
Kenny Root85387d72010-08-26 10:13:11 -07008031 private static boolean isForwardLocked(PackageParser.Package pkg) {
8032 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 }
8034
Kenny Root88670d82012-05-09 15:47:35 -07008035
8036 private boolean isForwardLocked(PackageSetting ps) {
8037 return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
8038 }
8039
Kenny Root85387d72010-08-26 10:13:11 -07008040 private static boolean isExternal(PackageParser.Package pkg) {
8041 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
8042 }
8043
Kenny Root6dceb882012-04-12 14:23:49 -07008044 private static boolean isExternal(PackageSetting ps) {
8045 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
8046 }
8047
Kenny Root85387d72010-08-26 10:13:11 -07008048 private static boolean isSystemApp(PackageParser.Package pkg) {
8049 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
8050 }
8051
Kenny Root502e9a42011-01-10 13:48:15 -08008052 private static boolean isSystemApp(ApplicationInfo info) {
8053 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
8054 }
8055
Kenny Root208d3412012-05-07 19:42:35 -07008056 private static boolean isSystemApp(PackageSetting ps) {
8057 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
8058 }
8059
Kenny Root85387d72010-08-26 10:13:11 -07008060 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
8061 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008062 }
8063
Kenny Root88670d82012-05-09 15:47:35 -07008064 private int packageFlagsToInstallFlags(PackageSetting ps) {
8065 int installFlags = 0;
8066 if (isExternal(ps)) {
8067 installFlags |= PackageManager.INSTALL_EXTERNAL;
8068 }
8069 if (isForwardLocked(ps)) {
8070 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
8071 }
8072 return installFlags;
8073 }
8074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 private void deleteTempPackageFiles() {
Kenny Root0b2fa8c2012-09-14 10:26:16 -07008076 final FilenameFilter filter = new FilenameFilter() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 public boolean accept(File dir, String name) {
8078 return name.startsWith("vmdl") && name.endsWith(".tmp");
8079 }
8080 };
Kenny Root0b2fa8c2012-09-14 10:26:16 -07008081 deleteTempPackageFilesInDirectory(mAppInstallDir, filter);
8082 deleteTempPackageFilesInDirectory(mDrmAppPrivateInstallDir, filter);
8083 }
8084
8085 private static final void deleteTempPackageFilesInDirectory(File directory,
8086 FilenameFilter filter) {
8087 final String[] tmpFilesList = directory.list(filter);
8088 if (tmpFilesList == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 return;
8090 }
Kenny Root0b2fa8c2012-09-14 10:26:16 -07008091 for (int i = 0; i < tmpFilesList.length; i++) {
8092 final File tmpFile = new File(directory, tmpFilesList[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093 tmpFile.delete();
8094 }
8095 }
8096
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008097 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 File tmpPackageFile;
8099 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008100 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008102 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 return null;
8104 }
8105 try {
8106 FileUtils.setPermissions(
8107 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
8108 -1, -1);
rpcraig554cb0c2012-07-05 06:41:43 -04008109 if (!SELinux.restorecon(tmpPackageFile)) {
8110 return null;
8111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008112 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008113 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 return null;
8115 }
8116 return tmpPackageFile;
8117 }
8118
Amith Yamasani67df64b2012-12-14 12:09:36 -08008119 @Override
8120 public void deletePackageAsUser(final String packageName,
8121 final IPackageDeleteObserver observer,
8122 final int userId, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 mContext.enforceCallingOrSelfPermission(
8124 android.Manifest.permission.DELETE_PACKAGES, null);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008125 final int uid = Binder.getCallingUid();
Amith Yamasani67df64b2012-12-14 12:09:36 -08008126 if (UserHandle.getUserId(uid) != userId) {
8127 mContext.enforceCallingPermission(
8128 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
8129 "deletePackage for user " + userId);
8130 }
8131 if (!isUserAllowed(userId, UserManager.ALLOW_UNINSTALL_APPS)) {
Amith Yamasanie4cf7342012-12-17 11:12:09 -08008132 try {
8133 observer.packageDeleted(packageName, PackageManager.DELETE_FAILED_USER_RESTRICTED);
8134 } catch (RemoteException re) {
8135 }
8136 return;
8137 }
8138
Amith Yamasani67df64b2012-12-14 12:09:36 -08008139 // Queue up an async operation since the package deletion may take a little while.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008140 mHandler.post(new Runnable() {
8141 public void run() {
8142 mHandler.removeCallbacks(this);
Amith Yamasani67df64b2012-12-14 12:09:36 -08008143 final int returnCode = deletePackageX(packageName, userId, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 if (observer != null) {
8145 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08008146 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 } catch (RemoteException e) {
8148 Log.i(TAG, "Observer no longer exists.");
8149 } //end catch
8150 } //end if
8151 } //end run
8152 });
8153 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 /**
8156 * This method is an internal method that could be get invoked either
8157 * to delete an installed package or to clean up a failed installation.
8158 * After deleting an installed package, a broadcast is sent to notify any
8159 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008160 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 * installation wouldn't have sent the initial broadcast either
8162 * The key steps in deleting a package are
8163 * deleting the package information in internal structures like mPackages,
8164 * deleting the packages base directories through installd
8165 * updating mSettings to reflect current status
8166 * persisting settings for later use
8167 * sending a broadcast if necessary
8168 */
Amith Yamasani67df64b2012-12-14 12:09:36 -08008169 private int deletePackageX(String packageName, int userId, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08008170 final PackageRemovedInfo info = new PackageRemovedInfo();
8171 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008173 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
8174 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
8175 try {
Amith Yamasani67df64b2012-12-14 12:09:36 -08008176 if (dpm != null && dpm.packageHasActiveAdmins(packageName, userId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008177 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Kenny Rootc39bb4a2011-02-28 13:27:19 -08008178 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008179 }
8180 } catch (RemoteException e) {
8181 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07008182
Dianne Hackbornc72fc672012-09-20 13:12:03 -07008183 boolean removedForAllUsers = false;
8184 boolean systemUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 synchronized (mInstallLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008186 res = deletePackageLI(packageName,
8187 (flags & PackageManager.DELETE_ALL_USERS) != 0
Amith Yamasani67df64b2012-12-14 12:09:36 -08008188 ? UserHandle.ALL : new UserHandle(userId),
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008189 true, flags | REMOVE_CHATTY, info, true);
Dianne Hackbornc72fc672012-09-20 13:12:03 -07008190 systemUpdate = info.isRemovedPackageSystemUpdate;
8191 if (res && !systemUpdate && mPackages.get(packageName) == null) {
8192 removedForAllUsers = true;
8193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008195
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008196 if (res) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07008197 info.sendBroadcast(true, systemUpdate, removedForAllUsers);
Romain Guy96f43572009-03-24 20:27:49 -07008198
Dianne Hackbornc72fc672012-09-20 13:12:03 -07008199 // If the removed package was a system update, the old system package
Romain Guy96f43572009-03-24 20:27:49 -07008200 // was re-enabled; we need to broadcast this information
8201 if (systemUpdate) {
8202 Bundle extras = new Bundle(1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008203 extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
8204 ? info.removedAppId : info.uid);
Romain Guy96f43572009-03-24 20:27:49 -07008205 extras.putBoolean(Intent.EXTRA_REPLACING, true);
8206
Dianne Hackborne7f97212011-02-24 14:40:20 -08008207 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008208 extras, null, null, null);
Dianne Hackborne7f97212011-02-24 14:40:20 -08008209 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008210 extras, null, null, null);
Dianne Hackborne7f97212011-02-24 14:40:20 -08008211 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008212 null, packageName, null, null);
Romain Guy96f43572009-03-24 20:27:49 -07008213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008214 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07008215 // Force a gc here.
8216 Runtime.getRuntime().gc();
8217 // Delete the resources here after sending the broadcast to let
8218 // other processes clean up before deleting resources.
8219 if (info.args != null) {
8220 synchronized (mInstallLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008221 info.args.doPostDeleteLI(true);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07008222 }
8223 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08008224
8225 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008226 }
8227
8228 static class PackageRemovedInfo {
8229 String removedPackage;
8230 int uid = -1;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008231 int removedAppId = -1;
8232 int[] removedUsers = null;
Romain Guy96f43572009-03-24 20:27:49 -07008233 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008234 // Clean up resources deleted packages.
8235 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07008236
Dianne Hackbornc72fc672012-09-20 13:12:03 -07008237 void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008238 Bundle extras = new Bundle(1);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008239 extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
8241 if (replacing) {
8242 extras.putBoolean(Intent.EXTRA_REPLACING, true);
8243 }
Dianne Hackbornc72fc672012-09-20 13:12:03 -07008244 extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08008246 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008247 extras, null, null, removedUsers);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07008248 if (fullRemove && !replacing) {
8249 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008250 extras, null, null, removedUsers);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07008251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008252 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008253 if (removedAppId >= 0) {
Amith Yamasani13593602012-03-22 16:16:17 -07008254 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008255 removedUsers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 }
8257 }
8258 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 /*
8261 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
8262 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008263 * 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 -08008264 * delete a partially installed application.
8265 */
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008266 private void removePackageDataLI(PackageSetting ps, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008267 int flags, boolean writeSettings) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008268 String packageName = ps.name;
8269 removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07008271 final PackageSetting deletedPs;
8272 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008273 synchronized (mPackages) {
8274 deletedPs = mSettings.mPackages.get(packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008275 if (outInfo != null) {
8276 outInfo.removedPackage = packageName;
8277 outInfo.removedUsers = deletedPs != null
Dianne Hackborn786b4402012-08-27 15:14:02 -07008278 ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
8279 : null;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008281 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008282 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
Dianne Hackborn4428e172012-08-24 17:43:05 -07008283 removeDataDirsLI(packageName);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008284 schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 }
Kenny Root447106f2011-03-23 11:00:15 -07008286 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08008288 if (deletedPs != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008289 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008290 if (outInfo != null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008291 outInfo.removedAppId = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008292 }
8293 if (deletedPs != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08008294 updatePermissionsLPw(deletedPs.name, null, 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008295 if (deletedPs.sharedUser != null) {
8296 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07008297 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008298 }
8299 }
Amith Yamasania3f133a2012-08-09 17:11:28 -07008300 clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08008301 }
8302 }
Kenny Root447106f2011-03-23 11:00:15 -07008303 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008304 if (writeSettings) {
8305 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07008306 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 }
8309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 /*
8312 * Tries to delete system package.
8313 */
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008314 private boolean deleteSystemPackageLI(PackageSetting newPs,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008315 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008316 PackageSetting disabledPs = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 // Confirm if the system package has been updated
8318 // An updated system app can be deleted. This will also have to restore
8319 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07008320 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 synchronized (mPackages) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008322 disabledPs = mSettings.getDisabledSystemPkgLPr(newPs.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008324 if (disabledPs == null) {
8325 Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008326 return false;
8327 } else {
8328 Log.i(TAG, "Deleting system pkg from data partition");
8329 }
8330 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07008331 outInfo.isRemovedPackageSystemUpdate = true;
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008332 if (disabledPs.versionCode < newPs.versionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008333 // Delete data for downgrades
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008334 flags &= ~PackageManager.DELETE_KEEP_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008335 } else {
8336 // Preserve data by setting flag
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008337 flags |= PackageManager.DELETE_KEEP_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008338 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008339 boolean ret = deleteInstalledPackageLI(newPs, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008340 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 if (!ret) {
8342 return false;
8343 }
Kenny Root447106f2011-03-23 11:00:15 -07008344 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 synchronized (mPackages) {
8346 // Reinstate the old system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008347 mSettings.enableSystemPackageLPw(newPs.name);
Kenny Root8f7cc022010-09-12 09:04:56 -07008348 // Remove any native libraries from the upgraded package.
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008349 NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 }
8351 // Install the system package
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008352 PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008353 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008354 SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 if (newPkg == null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008357 Slog.w(TAG, "Failed to restore system package:" + newPs.name
8358 + " with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 return false;
8360 }
Kenny Root447106f2011-03-23 11:00:15 -07008361 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 synchronized (mPackages) {
Dianne Hackborne639da72012-02-21 15:11:13 -08008363 updatePermissionsLPw(newPkg.packageName, newPkg,
8364 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
Kenny Root447106f2011-03-23 11:00:15 -07008365 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008366 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07008367 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 }
8370 return true;
8371 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008372
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008373 private boolean deleteInstalledPackageLI(PackageSetting ps,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008374 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
8375 boolean writeSettings) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008376 if (outInfo != null) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008377 outInfo.uid = ps.appId;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379
8380 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008381 removePackageDataLI(ps, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382
8383 // Delete application code and resources
Kenny Root92bc9b32012-10-23 17:42:40 -07008384 if (deleteCodeAndResources && (outInfo != null)) {
Kenny Root5455f682012-09-09 14:52:10 -07008385 outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008386 ps.resourcePathString, ps.nativeLibraryPathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008387 }
8388 return true;
8389 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 /*
8392 * This method handles package deletion in general
8393 */
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008394 private boolean deletePackageLI(String packageName, UserHandle user,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008395 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
8396 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008397 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008398 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 return false;
8400 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008401 PackageSetting ps;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008402 boolean dataOnly = false;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008403 int removeUser = -1;
8404 int appId = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008405 synchronized (mPackages) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008406 ps = mSettings.mPackages.get(packageName);
8407 if (ps == null) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008408 Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
8409 return false;
8410 }
Amith Yamasani67df64b2012-12-14 12:09:36 -08008411 if (user != null
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008412 && user.getIdentifier() != UserHandle.USER_ALL) {
8413 // The caller is asking that the package only be deleted for a single
8414 // user. To do this, we just mark its uninstalled state and delete
8415 // its data.
8416 ps.setUserState(user.getIdentifier(),
8417 COMPONENT_ENABLED_STATE_DEFAULT,
8418 false, //installed
8419 true, //stopped
8420 true, //notLaunched
8421 null, null);
Amith Yamasani67df64b2012-12-14 12:09:36 -08008422 if (!isSystemApp(ps)) {
8423 if (ps.isAnyInstalled(sUserManager.getUserIds())) {
8424 // Other user still have this package installed, so all
8425 // we need to do is clear this user's data and save that
8426 // it is uninstalled.
8427 removeUser = user.getIdentifier();
8428 appId = ps.appId;
8429 mSettings.writePackageRestrictionsLPr(removeUser);
8430 } else {
8431 // We need to set it back to 'installed' so the uninstall
8432 // broadcasts will be sent correctly.
8433 ps.setInstalled(true, user.getIdentifier());
8434 }
8435 } else {
8436 // This is a system app, so we assume that the
8437 // other users still have this package installed, so all
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008438 // we need to do is clear this user's data and save that
8439 // it is uninstalled.
8440 removeUser = user.getIdentifier();
8441 appId = ps.appId;
8442 mSettings.writePackageRestrictionsLPr(removeUser);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008443 }
8444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008446
8447 if (removeUser >= 0) {
8448 // From above, we determined that we are deleting this only
8449 // for a single user. Continue the work here.
8450 if (outInfo != null) {
8451 outInfo.removedPackage = packageName;
8452 outInfo.removedAppId = appId;
8453 outInfo.removedUsers = new int[] {removeUser};
8454 }
8455 mInstaller.clearUserData(packageName, removeUser);
8456 schedulePackageCleaning(packageName, removeUser, false);
8457 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 if (dataOnly) {
8461 // Delete application data first
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008462 removePackageDataLI(ps, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 return true;
8464 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08008465
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008466 boolean ret = false;
Geremy Condraf1bcca82013-01-07 22:35:24 -08008467 mSettings.mKeySetManager.removeAppKeySetData(packageName);
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008468 if (isSystemApp(ps)) {
8469 Log.i(TAG, "Removing system package:" + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 // When an updated system application is deleted we delete the existing resources as well and
8471 // fall back to existing code in system partition
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008472 ret = deleteSystemPackageLI(ps, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008473 } else {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008474 Log.i(TAG, "Removing non-system package:" + ps.name);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008475 // Kill application pre-emptively especially for apps on sd.
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -07008476 killApplication(packageName, ps.appId);
8477 ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008478 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08008480
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008481 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008483
Dianne Hackborn183ce022012-06-29 15:00:21 -07008484 private final class ClearStorageConnection implements ServiceConnection {
8485 IMediaContainerService mContainerService;
8486
8487 @Override
8488 public void onServiceConnected(ComponentName name, IBinder service) {
8489 synchronized (this) {
8490 mContainerService = IMediaContainerService.Stub.asInterface(service);
8491 notifyAll();
8492 }
8493 }
8494
8495 @Override
8496 public void onServiceDisconnected(ComponentName name) {
8497 }
8498 }
8499
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008500 private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
Dianne Hackborn183ce022012-06-29 15:00:21 -07008501 final boolean mounted;
8502 if (Environment.isExternalStorageEmulated()) {
8503 mounted = true;
8504 } else {
8505 final String status = Environment.getExternalStorageState();
8506
8507 mounted = status.equals(Environment.MEDIA_MOUNTED)
8508 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
8509 }
8510
8511 if (!mounted) {
8512 return;
8513 }
8514
8515 final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008516 int[] users;
8517 if (userId == UserHandle.USER_ALL) {
8518 users = sUserManager.getUserIds();
8519 } else {
8520 users = new int[] { userId };
8521 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07008522 final ClearStorageConnection conn = new ClearStorageConnection();
Amith Yamasani27b89e62013-01-16 12:30:11 -08008523 if (mContext.bindServiceAsUser(
8524 containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
Jeff Sharkey752cd922012-09-23 16:25:12 -07008525 try {
8526 for (int curUser : users) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008527 long timeout = SystemClock.uptimeMillis() + 5000;
8528 synchronized (conn) {
8529 long now = SystemClock.uptimeMillis();
8530 while (conn.mContainerService == null && now < timeout) {
8531 try {
8532 conn.wait(timeout - now);
8533 } catch (InterruptedException e) {
8534 }
Dianne Hackborn183ce022012-06-29 15:00:21 -07008535 }
8536 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008537 if (conn.mContainerService == null) {
8538 return;
8539 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07008540
8541 final UserEnvironment userEnv = new UserEnvironment(curUser);
8542 final File externalCacheDir = userEnv
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008543 .getExternalStorageAppCacheDirectory(packageName);
Dianne Hackborn183ce022012-06-29 15:00:21 -07008544 try {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008545 conn.mContainerService.clearDirectory(externalCacheDir.toString());
Dianne Hackborn183ce022012-06-29 15:00:21 -07008546 } catch (RemoteException e) {
8547 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008548 if (allData) {
Jeff Sharkeyb049e212012-09-07 23:16:01 -07008549 final File externalDataDir = userEnv
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008550 .getExternalStorageAppDataDirectory(packageName);
8551 try {
8552 conn.mContainerService.clearDirectory(externalDataDir.toString());
8553 } catch (RemoteException e) {
8554 }
Jeff Sharkeyb049e212012-09-07 23:16:01 -07008555 final File externalMediaDir = userEnv
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008556 .getExternalStorageAppMediaDirectory(packageName);
8557 try {
8558 conn.mContainerService.clearDirectory(externalMediaDir.toString());
8559 } catch (RemoteException e) {
8560 }
Dianne Hackborn183ce022012-06-29 15:00:21 -07008561 }
8562 }
Jeff Sharkey752cd922012-09-23 16:25:12 -07008563 } finally {
8564 mContext.unbindService(conn);
Dianne Hackborn183ce022012-06-29 15:00:21 -07008565 }
8566 }
8567 }
8568
Amith Yamasani483f3b02012-03-13 16:08:00 -07008569 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 public void clearApplicationUserData(final String packageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008571 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 mContext.enforceCallingOrSelfPermission(
8573 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
Amith Yamasanif203aee2012-08-29 18:41:53 -07008574 enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "clear application data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 // Queue up an async operation since the package deletion may take a little while.
8576 mHandler.post(new Runnable() {
8577 public void run() {
8578 mHandler.removeCallbacks(this);
8579 final boolean succeeded;
8580 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008581 succeeded = clearApplicationUserDataLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008582 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008583 clearExternalStorageDataSync(packageName, userId, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008584 if (succeeded) {
8585 // invoke DeviceStorageMonitor's update method to clear any notifications
8586 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
8587 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
8588 if (dsm != null) {
8589 dsm.updateMemory();
8590 }
8591 }
8592 if(observer != null) {
8593 try {
8594 observer.onRemoveCompleted(packageName, succeeded);
8595 } catch (RemoteException e) {
8596 Log.i(TAG, "Observer no longer exists.");
8597 }
8598 } //end if observer
8599 } //end run
8600 });
8601 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008602
Amith Yamasani483f3b02012-03-13 16:08:00 -07008603 private boolean clearApplicationUserDataLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008604 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008605 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 return false;
8607 }
8608 PackageParser.Package p;
8609 boolean dataOnly = false;
8610 synchronized (mPackages) {
8611 p = mPackages.get(packageName);
8612 if(p == null) {
8613 dataOnly = true;
8614 PackageSetting ps = mSettings.mPackages.get(packageName);
8615 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008616 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 return false;
8618 }
8619 p = ps.pkg;
8620 }
8621 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08008622
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08008623 if (!dataOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 //need to check this only for fully installed applications
8625 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008626 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 return false;
8628 }
8629 final ApplicationInfo applicationInfo = p.applicationInfo;
8630 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008631 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 return false;
8633 }
8634 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008635 int retCode = mInstaller.clearUserData(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008636 if (retCode < 0) {
8637 Slog.w(TAG, "Couldn't remove cache files for package: "
8638 + packageName);
8639 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008640 }
8641 return true;
8642 }
8643
8644 public void deleteApplicationCacheFiles(final String packageName,
8645 final IPackageDataObserver observer) {
8646 mContext.enforceCallingOrSelfPermission(
8647 android.Manifest.permission.DELETE_CACHE_FILES, null);
8648 // Queue up an async operation since the package deletion may take a little while.
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07008649 final int userId = UserHandle.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 mHandler.post(new Runnable() {
8651 public void run() {
8652 mHandler.removeCallbacks(this);
8653 final boolean succeded;
8654 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008655 succeded = deleteApplicationCacheFilesLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07008657 clearExternalStorageDataSync(packageName, userId, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008658 if(observer != null) {
8659 try {
8660 observer.onRemoveCompleted(packageName, succeded);
8661 } catch (RemoteException e) {
8662 Log.i(TAG, "Observer no longer exists.");
8663 }
8664 } //end if observer
8665 } //end run
8666 });
8667 }
8668
Amith Yamasani483f3b02012-03-13 16:08:00 -07008669 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008671 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 return false;
8673 }
8674 PackageParser.Package p;
8675 synchronized (mPackages) {
8676 p = mPackages.get(packageName);
8677 }
8678 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008679 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 return false;
8681 }
8682 final ApplicationInfo applicationInfo = p.applicationInfo;
8683 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008684 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008685 return false;
8686 }
Amith Yamasani54289b82012-10-01 10:39:14 -07008687 int retCode = mInstaller.deleteCacheFiles(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008688 if (retCode < 0) {
8689 Slog.w(TAG, "Couldn't remove cache files for package: "
Amith Yamasani54289b82012-10-01 10:39:14 -07008690 + packageName + " u" + userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008691 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 }
8693 return true;
8694 }
8695
Dianne Hackborn0c380492012-08-20 17:23:30 -07008696 public void getPackageSizeInfo(final String packageName, int userHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 final IPackageStatsObserver observer) {
8698 mContext.enforceCallingOrSelfPermission(
8699 android.Manifest.permission.GET_PACKAGE_SIZE, null);
Kenny Root366949c2011-01-14 17:18:14 -08008700
Dianne Hackborn0c380492012-08-20 17:23:30 -07008701 PackageStats stats = new PackageStats(packageName, userHandle);
Kenny Root366949c2011-01-14 17:18:14 -08008702
Kenny Roota69b7eb2012-05-14 14:47:06 -07008703 /*
8704 * Queue up an async operation since the package measurement may take a
8705 * little while.
8706 */
8707 Message msg = mHandler.obtainMessage(INIT_COPY);
8708 msg.obj = new MeasureParams(stats, observer);
8709 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008710 }
8711
Dianne Hackborn0c380492012-08-20 17:23:30 -07008712 private boolean getPackageSizeInfoLI(String packageName, int userHandle,
8713 PackageStats pStats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008714 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008715 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 return false;
8717 }
8718 PackageParser.Package p;
8719 boolean dataOnly = false;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008720 String asecPath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 synchronized (mPackages) {
8722 p = mPackages.get(packageName);
8723 if(p == null) {
8724 dataOnly = true;
8725 PackageSetting ps = mSettings.mPackages.get(packageName);
8726 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008727 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 return false;
8729 }
8730 p = ps.pkg;
8731 }
Kenny Root2afded12012-06-04 16:39:47 -07008732 if (p != null && (isExternal(p) || isForwardLocked(p))) {
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008733 String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
8734 if (secureContainerId != null) {
8735 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
8736 }
8737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 }
8739 String publicSrcDir = null;
8740 if(!dataOnly) {
8741 final ApplicationInfo applicationInfo = p.applicationInfo;
8742 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008743 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008744 return false;
8745 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008746 if (isForwardLocked(p)) {
8747 publicSrcDir = applicationInfo.publicSourceDir;
8748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 }
Dianne Hackborn0c380492012-08-20 17:23:30 -07008750 int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, publicSrcDir,
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008751 asecPath, pStats);
8752 if (res < 0) {
8753 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 }
Kenny Root2afded12012-06-04 16:39:47 -07008755
8756 // Fix-up for forward-locked applications in ASEC containers.
8757 if (!isExternal(p)) {
8758 pStats.codeSize += pStats.externalCodeSize;
8759 pStats.externalCodeSize = 0L;
8760 }
8761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 return true;
8763 }
8764
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008766 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07008767 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 }
8769
8770 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07008771 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008772 }
8773
8774 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08008775 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 }
8777
Kenny Root447106f2011-03-23 11:00:15 -07008778 private int getUidTargetSdkVersionLockedLPr(int uid) {
8779 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008780 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07008781 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008782 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07008783 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008784 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07008785 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008786 if (ps.pkg != null) {
8787 int v = ps.pkg.applicationInfo.targetSdkVersion;
8788 if (v < vers) vers = v;
8789 }
8790 }
8791 return vers;
8792 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07008793 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008794 if (ps.pkg != null) {
8795 return ps.pkg.applicationInfo.targetSdkVersion;
8796 }
8797 }
8798 return Build.VERSION_CODES.CUR_DEVELOPMENT;
8799 }
8800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 public void addPreferredActivity(IntentFilter filter, int match,
Amith Yamasania3f133a2012-08-09 17:11:28 -07008802 ComponentName[] set, ComponentName activity, int userId) {
Kenny Root447106f2011-03-23 11:00:15 -07008803 // writer
Amith Yamasania3f133a2012-08-09 17:11:28 -07008804 int callingUid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -07008805 enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008807 if (mContext.checkCallingOrSelfPermission(
8808 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8809 != PackageManager.PERMISSION_GRANTED) {
Amith Yamasania3f133a2012-08-09 17:11:28 -07008810 if (getUidTargetSdkVersionLockedLPr(callingUid)
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008811 < Build.VERSION_CODES.FROYO) {
8812 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
Amith Yamasania3f133a2012-08-09 17:11:28 -07008813 + callingUid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008814 return;
8815 }
8816 mContext.enforceCallingOrSelfPermission(
8817 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8818 }
Amith Yamasania3f133a2012-08-09 17:11:28 -07008819
8820 Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
Dianne Hackborn63092712012-10-07 14:45:35 -07008822 mSettings.editPreferredActivitiesLPw(userId).addFilter(
8823 new PreferredActivity(filter, match, set, activity));
8824 mSettings.writePackageRestrictionsLPr(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008825 }
8826 }
8827
Satish Sampath8dbe6122009-06-02 23:35:54 +01008828 public void replacePreferredActivity(IntentFilter filter, int match,
8829 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01008830 if (filter.countActions() != 1) {
8831 throw new IllegalArgumentException(
8832 "replacePreferredActivity expects filter to have only 1 action.");
8833 }
8834 if (filter.countCategories() != 1) {
8835 throw new IllegalArgumentException(
8836 "replacePreferredActivity expects filter to have only 1 category.");
8837 }
8838 if (filter.countDataAuthorities() != 0
8839 || filter.countDataPaths() != 0
8840 || filter.countDataSchemes() != 0
8841 || filter.countDataTypes() != 0) {
8842 throw new IllegalArgumentException(
8843 "replacePreferredActivity expects filter to have no data authorities, " +
8844 "paths, schemes or types.");
8845 }
8846 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008847 if (mContext.checkCallingOrSelfPermission(
8848 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8849 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008850 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008851 < Build.VERSION_CODES.FROYO) {
8852 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
8853 + Binder.getCallingUid());
8854 return;
8855 }
8856 mContext.enforceCallingOrSelfPermission(
8857 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8858 }
Amith Yamasania3f133a2012-08-09 17:11:28 -07008859
8860 final int callingUserId = UserHandle.getCallingUserId();
Dianne Hackborn04505102012-02-29 12:34:04 -08008861 ArrayList<PreferredActivity> removed = null;
Dianne Hackborn63092712012-10-07 14:45:35 -07008862 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(callingUserId);
8863 if (pir != null) {
8864 Iterator<PreferredActivity> it = pir.filterIterator();
8865 String action = filter.getAction(0);
8866 String category = filter.getCategory(0);
8867 while (it.hasNext()) {
8868 PreferredActivity pa = it.next();
8869 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
8870 if (removed == null) {
8871 removed = new ArrayList<PreferredActivity>();
8872 }
8873 removed.add(pa);
8874 Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
8875 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
Dianne Hackborn04505102012-02-29 12:34:04 -08008876 }
Satish Sampath8dbe6122009-06-02 23:35:54 +01008877 }
Dianne Hackborn63092712012-10-07 14:45:35 -07008878 if (removed != null) {
8879 for (int i=0; i<removed.size(); i++) {
8880 PreferredActivity pa = removed.get(i);
8881 pir.removeFilter(pa);
8882 }
Dianne Hackborn04505102012-02-29 12:34:04 -08008883 }
8884 }
Amith Yamasania3f133a2012-08-09 17:11:28 -07008885 addPreferredActivity(filter, match, set, activity, callingUserId);
Satish Sampath8dbe6122009-06-02 23:35:54 +01008886 }
8887 }
8888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008889 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07008890 final int uid = Binder.getCallingUid();
8891 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008892 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08008893 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008894 if (pkg == null || pkg.applicationInfo.uid != uid) {
8895 if (mContext.checkCallingOrSelfPermission(
8896 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8897 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008898 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008899 < Build.VERSION_CODES.FROYO) {
8900 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
8901 + Binder.getCallingUid());
8902 return;
8903 }
8904 mContext.enforceCallingOrSelfPermission(
8905 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8906 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08008907 }
8908
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08008909 int user = UserHandle.getCallingUserId();
8910 if (clearPackagePreferredActivitiesLPw(packageName, user)) {
8911 mSettings.writePackageRestrictionsLPr(user);
8912 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008913 }
8914 }
8915 }
8916
Amith Yamasania3f133a2012-08-09 17:11:28 -07008917 /** This method takes a specific user id as well as UserHandle.USER_ALL. */
8918 boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008919 ArrayList<PreferredActivity> removed = null;
Dianne Hackborn63092712012-10-07 14:45:35 -07008920 boolean changed = false;
8921 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
8922 final int thisUserId = mSettings.mPreferredActivities.keyAt(i);
8923 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
8924 if (userId != UserHandle.USER_ALL && userId != thisUserId) {
Amith Yamasania3f133a2012-08-09 17:11:28 -07008925 continue;
8926 }
Dianne Hackborn63092712012-10-07 14:45:35 -07008927 Iterator<PreferredActivity> it = pir.filterIterator();
8928 while (it.hasNext()) {
8929 PreferredActivity pa = it.next();
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08008930 if (packageName == null ||
8931 pa.mPref.mComponent.getPackageName().equals(packageName)) {
Dianne Hackborn63092712012-10-07 14:45:35 -07008932 if (removed == null) {
8933 removed = new ArrayList<PreferredActivity>();
8934 }
8935 removed.add(pa);
Dianne Hackborn04505102012-02-29 12:34:04 -08008936 }
Dianne Hackborn63092712012-10-07 14:45:35 -07008937 }
8938 if (removed != null) {
8939 for (int j=0; j<removed.size(); j++) {
8940 PreferredActivity pa = removed.get(j);
8941 pir.removeFilter(pa);
8942 }
8943 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008944 }
8945 }
Dianne Hackborn63092712012-10-07 14:45:35 -07008946 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 }
8948
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08008949 public void resetPreferredActivities(int userId) {
8950 mContext.enforceCallingOrSelfPermission(
8951 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8952 // writer
8953 synchronized (mPackages) {
8954 int user = UserHandle.getCallingUserId();
8955 clearPackagePreferredActivitiesLPw(null, user);
8956 mSettings.readDefaultPreferredAppsLPw(this, user);
8957 mSettings.writePackageRestrictionsLPr(user);
8958 scheduleWriteSettingsLocked();
8959 }
8960 }
8961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 public int getPreferredActivities(List<IntentFilter> outFilters,
8963 List<ComponentName> outActivities, String packageName) {
8964
8965 int num = 0;
Amith Yamasania3f133a2012-08-09 17:11:28 -07008966 final int userId = UserHandle.getCallingUserId();
Kenny Root447106f2011-03-23 11:00:15 -07008967 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 synchronized (mPackages) {
Dianne Hackborn63092712012-10-07 14:45:35 -07008969 PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
8970 if (pir != null) {
8971 final Iterator<PreferredActivity> it = pir.filterIterator();
8972 while (it.hasNext()) {
8973 final PreferredActivity pa = it.next();
8974 if (packageName == null
8975 || pa.mPref.mComponent.getPackageName().equals(packageName)) {
8976 if (outFilters != null) {
8977 outFilters.add(new IntentFilter(pa));
8978 }
8979 if (outActivities != null) {
8980 outActivities.add(pa.mPref.mComponent);
8981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 }
8983 }
8984 }
8985 }
8986
8987 return num;
8988 }
8989
Amith Yamasani483f3b02012-03-13 16:08:00 -07008990 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 public void setApplicationEnabledSetting(String appPackageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008992 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008993 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008994 setEnabledSetting(appPackageName, null, newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 }
8996
Amith Yamasani483f3b02012-03-13 16:08:00 -07008997 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 public void setComponentEnabledSetting(ComponentName componentName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008999 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07009000 if (!sUserManager.exists(userId)) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 setEnabledSetting(componentName.getPackageName(),
Amith Yamasani483f3b02012-03-13 16:08:00 -07009002 componentName.getClassName(), newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009003 }
9004
9005 private void setEnabledSetting(
Amith Yamasani483f3b02012-03-13 16:08:00 -07009006 final String packageName, String className, int newState, final int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009007 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
9008 || newState == COMPONENT_ENABLED_STATE_ENABLED
Dianne Hackborn0ac30312011-06-17 14:49:23 -07009009 || newState == COMPONENT_ENABLED_STATE_DISABLED
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08009010 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER
9011 || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009012 throw new IllegalArgumentException("Invalid new component state: "
9013 + newState);
9014 }
9015 PackageSetting pkgSetting;
9016 final int uid = Binder.getCallingUid();
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08009017 final int permission = mContext.checkCallingOrSelfPermission(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009018 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
Amith Yamasanif203aee2012-08-29 18:41:53 -07009019 enforceCrossUserPermission(uid, userId, false, "set enabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009021 boolean sendNow = false;
9022 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009023 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009025 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -07009026
9027 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009028 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009029 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009030 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009031 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009032 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009033 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 }
9035 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009036 "Unknown component: " + packageName
9037 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009038 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07009039 // Allow root and verify that userId is not being specified by a different user
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07009040 if (!allowedByPermission && !UserHandle.isSameApp(uid, pkgSetting.appId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 throw new SecurityException(
9042 "Permission Denial: attempt to change component state from pid="
9043 + Binder.getCallingPid()
Amith Yamasani13593602012-03-22 16:16:17 -07009044 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009046 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 // We're dealing with an application/package level state change
Amith Yamasani483f3b02012-03-13 16:08:00 -07009048 if (pkgSetting.getEnabled(userId) == newState) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07009049 // Nothing to do
9050 return;
9051 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07009052 pkgSetting.setEnabled(newState, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07009053 // pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 } else {
9055 // We're dealing with a component level state change
Dianne Hackborn65696252012-03-05 18:49:21 -08009056 // First, verify that this is a valid class name.
9057 PackageParser.Package pkg = pkgSetting.pkg;
9058 if (pkg == null || !pkg.hasComponentClassName(className)) {
9059 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
9060 throw new IllegalArgumentException("Component class " + className
9061 + " does not exist in " + packageName);
9062 } else {
9063 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
9064 + className + " does not exist in " + packageName);
9065 }
9066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009067 switch (newState) {
9068 case COMPONENT_ENABLED_STATE_ENABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07009069 if (!pkgSetting.enableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07009070 return;
9071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 break;
9073 case COMPONENT_ENABLED_STATE_DISABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07009074 if (!pkgSetting.disableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07009075 return;
9076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 break;
9078 case COMPONENT_ENABLED_STATE_DEFAULT:
Amith Yamasani483f3b02012-03-13 16:08:00 -07009079 if (!pkgSetting.restoreComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07009080 return;
9081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 break;
9083 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009084 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009085 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 }
9087 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07009088 mSettings.writePackageRestrictionsLPr(userId);
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07009089 packageUid = UserHandle.getUid(userId, pkgSetting.appId);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009090 components = mPendingBroadcasts.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07009091 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009092 if (newPackage) {
9093 components = new ArrayList<String>();
9094 }
9095 if (!components.contains(componentName)) {
9096 components.add(componentName);
9097 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009098 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
9099 sendNow = true;
9100 // Purge entry from pending broadcast list if another one exists already
9101 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009102 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009103 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009104 if (newPackage) {
9105 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009106 }
9107 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
9108 // Schedule a message
9109 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
9110 }
9111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 long callingId = Binder.clearCallingIdentity();
9115 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009116 if (sendNow) {
9117 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009118 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 } finally {
9121 Binder.restoreCallingIdentity(callingId);
9122 }
9123 }
9124
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009125 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009126 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08009127 if (DEBUG_INSTALL)
9128 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
9129 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08009130 Bundle extras = new Bundle(4);
9131 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
9132 String nameList[] = new String[componentNames.size()];
9133 componentNames.toArray(nameList);
9134 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009135 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
9136 extras.putInt(Intent.EXTRA_UID, packageUid);
Amith Yamasani13593602012-03-22 16:16:17 -07009137 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009138 new int[] {UserHandle.getUserId(packageUid)});
Dianne Hackborne7f97212011-02-24 14:40:20 -08009139 }
9140
Amith Yamasani483f3b02012-03-13 16:08:00 -07009141 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07009142 if (!sUserManager.exists(userId)) return;
Dianne Hackborne7f97212011-02-24 14:40:20 -08009143 final int uid = Binder.getCallingUid();
9144 final int permission = mContext.checkCallingOrSelfPermission(
9145 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
9146 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Amith Yamasanif203aee2012-08-29 18:41:53 -07009147 enforceCrossUserPermission(uid, userId, true, "stop package");
Kenny Root447106f2011-03-23 11:00:15 -07009148 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -08009149 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07009150 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
Amith Yamasani483f3b02012-03-13 16:08:00 -07009151 uid, userId)) {
9152 scheduleWritePackageRestrictionsLocked(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009153 }
9154 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07009155 }
9156
Jacek Surazski65e13172009-04-28 15:26:38 +02009157 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07009158 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +02009159 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07009160 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02009161 }
9162 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009163
Amith Yamasani483f3b02012-03-13 16:08:00 -07009164 @Override
9165 public int getApplicationEnabledSetting(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07009166 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07009167 int uid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -07009168 enforceCrossUserPermission(uid, userId, false, "get enabled");
Kenny Root447106f2011-03-23 11:00:15 -07009169 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07009171 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 }
9173 }
9174
Amith Yamasani483f3b02012-03-13 16:08:00 -07009175 @Override
9176 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07009177 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07009178 int uid = Binder.getCallingUid();
Amith Yamasanif203aee2012-08-29 18:41:53 -07009179 enforceCrossUserPermission(uid, userId, false, "get component enabled");
Kenny Root447106f2011-03-23 11:00:15 -07009180 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07009182 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 }
9184 }
9185
9186 public void enterSafeMode() {
Kenny Root461ff1f2011-08-09 09:43:03 -07009187 enforceSystemOrRoot("Only the system can request entering safe mode");
9188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 if (!mSystemReady) {
9190 mSafeMode = true;
9191 }
9192 }
9193
9194 public void systemReady() {
9195 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07009196
9197 // Read the compatibilty setting when the system is ready.
Jeff Sharkey6e2bee72012-10-01 13:39:08 -07009198 boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07009199 mContext.getContentResolver(),
Jeff Sharkey6e2bee72012-10-01 13:39:08 -07009200 android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07009201 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07009202 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07009203 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07009204 }
Dianne Hackborn63092712012-10-07 14:45:35 -07009205
9206 synchronized (mPackages) {
9207 // Verify that all of the preferred activity components actually
9208 // exist. It is possible for applications to be updated and at
9209 // that point remove a previously declared activity component that
9210 // had been set as a preferred activity. We try to clean this up
9211 // the next time we encounter that preferred activity, but it is
9212 // possible for the user flow to never be able to return to that
9213 // situation so here we do a sanity check to make sure we haven't
9214 // left any junk around.
9215 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
9216 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
9217 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
9218 removed.clear();
9219 for (PreferredActivity pa : pir.filterSet()) {
9220 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
9221 removed.add(pa);
9222 }
9223 }
9224 if (removed.size() > 0) {
9225 for (int j=0; j<removed.size(); j++) {
9226 PreferredActivity pa = removed.get(i);
Dianne Hackborn63092712012-10-07 14:45:35 -07009227 Slog.w(TAG, "Removing dangling preferred activity: "
Dianne Hackborn40e9f292012-11-27 19:12:23 -08009228 + pa.mPref.mComponent);
Dianne Hackborn63092712012-10-07 14:45:35 -07009229 pir.removeFilter(pa);
9230 }
9231 mSettings.writePackageRestrictionsLPr(
9232 mSettings.mPreferredActivities.keyAt(i));
9233 }
9234 }
9235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 }
9237
9238 public boolean isSafeMode() {
9239 return mSafeMode;
9240 }
9241
9242 public boolean hasSystemUidErrors() {
9243 return mHasSystemUidErrors;
9244 }
9245
9246 static String arrayToString(int[] array) {
9247 StringBuffer buf = new StringBuffer(128);
9248 buf.append('[');
9249 if (array != null) {
9250 for (int i=0; i<array.length; i++) {
9251 if (i > 0) buf.append(", ");
9252 buf.append(array[i]);
9253 }
9254 }
9255 buf.append(']');
9256 return buf.toString();
9257 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009258
Kenny Root447106f2011-03-23 11:00:15 -07009259 static class DumpState {
9260 public static final int DUMP_LIBS = 1 << 0;
9261
9262 public static final int DUMP_FEATURES = 1 << 1;
9263
9264 public static final int DUMP_RESOLVERS = 1 << 2;
9265
9266 public static final int DUMP_PERMISSIONS = 1 << 3;
9267
9268 public static final int DUMP_PACKAGES = 1 << 4;
9269
9270 public static final int DUMP_SHARED_USERS = 1 << 5;
9271
9272 public static final int DUMP_MESSAGES = 1 << 6;
9273
9274 public static final int DUMP_PROVIDERS = 1 << 7;
9275
Kenny Root05ca4c92011-09-15 10:36:25 -07009276 public static final int DUMP_VERIFIERS = 1 << 8;
9277
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009278 public static final int DUMP_PREFERRED = 1 << 9;
9279
9280 public static final int DUMP_PREFERRED_XML = 1 << 10;
9281
Geremy Condraf1bcca82013-01-07 22:35:24 -08009282 public static final int DUMP_KEYSETS = 1 << 11;
9283
Kenny Root447106f2011-03-23 11:00:15 -07009284 public static final int OPTION_SHOW_FILTERS = 1 << 0;
9285
9286 private int mTypes;
9287
9288 private int mOptions;
9289
9290 private boolean mTitlePrinted;
9291
9292 private SharedUserSetting mSharedUser;
9293
9294 public boolean isDumping(int type) {
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009295 if (mTypes == 0 && type != DUMP_PREFERRED_XML) {
Kenny Root447106f2011-03-23 11:00:15 -07009296 return true;
9297 }
9298
9299 return (mTypes & type) != 0;
9300 }
9301
9302 public void setDump(int type) {
9303 mTypes |= type;
9304 }
9305
9306 public boolean isOptionEnabled(int option) {
9307 return (mOptions & option) != 0;
9308 }
9309
9310 public void setOptionEnabled(int option) {
9311 mOptions |= option;
9312 }
9313
9314 public boolean onTitlePrinted() {
9315 final boolean printed = mTitlePrinted;
9316 mTitlePrinted = true;
9317 return printed;
9318 }
9319
9320 public boolean getTitlePrinted() {
9321 return mTitlePrinted;
9322 }
9323
9324 public void setTitlePrinted(boolean enabled) {
9325 mTitlePrinted = enabled;
9326 }
9327
9328 public SharedUserSetting getSharedUser() {
9329 return mSharedUser;
9330 }
9331
9332 public void setSharedUser(SharedUserSetting user) {
9333 mSharedUser = user;
9334 }
9335 }
9336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 @Override
9338 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
9339 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
9340 != PackageManager.PERMISSION_GRANTED) {
9341 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9342 + Binder.getCallingPid()
9343 + ", uid=" + Binder.getCallingUid()
9344 + " without permission "
9345 + android.Manifest.permission.DUMP);
9346 return;
9347 }
9348
Kenny Root447106f2011-03-23 11:00:15 -07009349 DumpState dumpState = new DumpState();
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08009350 boolean fullPreferred = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009351
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009352 String packageName = null;
9353
9354 int opti = 0;
9355 while (opti < args.length) {
9356 String opt = args[opti];
9357 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9358 break;
9359 }
9360 opti++;
9361 if ("-a".equals(opt)) {
9362 // Right now we only know how to print all.
9363 } else if ("-h".equals(opt)) {
9364 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009365 pw.println(" [-h] [-f] [cmd] ...");
9366 pw.println(" -f: print details of intent filters");
9367 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009368 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009369 pw.println(" l[ibraries]: list known shared libraries");
9370 pw.println(" f[ibraries]: list device features");
9371 pw.println(" r[esolvers]: dump intent resolvers");
9372 pw.println(" perm[issions]: dump permissions");
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009373 pw.println(" pref[erred]: print preferred package settings");
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08009374 pw.println(" preferred-xml [--full]: print preferred package settings as xml");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009375 pw.println(" prov[iders]: dump content providers");
9376 pw.println(" p[ackages]: dump installed packages");
9377 pw.println(" s[hared-users]: dump shared user IDs");
9378 pw.println(" m[essages]: print collected runtime messages");
Kenny Root05ca4c92011-09-15 10:36:25 -07009379 pw.println(" v[erifiers]: print package verifier info");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009380 pw.println(" <package.name>: info about given package");
Geremy Condraf1bcca82013-01-07 22:35:24 -08009381 pw.println(" k[eysets]: print known keysets");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009382 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009383 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -07009384 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009385 } else {
9386 pw.println("Unknown argument: " + opt + "; use -h for help");
9387 }
9388 }
9389
9390 // Is the caller requesting to dump a particular piece of data?
9391 if (opti < args.length) {
9392 String cmd = args[opti];
9393 opti++;
9394 // Is this a package name?
9395 if ("android".equals(cmd) || cmd.contains(".")) {
9396 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009397 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009398 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009399 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009400 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009401 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009402 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009403 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009404 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009405 } else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
9406 dumpState.setDump(DumpState.DUMP_PREFERRED);
9407 } else if ("preferred-xml".equals(cmd)) {
9408 dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08009409 if (opti < args.length && "--full".equals(args[opti])) {
9410 fullPreferred = true;
Dianne Hackbornd4d93642013-01-29 16:12:48 -08009411 opti++;
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08009412 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009413 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009414 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009415 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009416 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009417 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009418 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009419 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07009420 dumpState.setDump(DumpState.DUMP_MESSAGES);
Kenny Root05ca4c92011-09-15 10:36:25 -07009421 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
9422 dumpState.setDump(DumpState.DUMP_VERIFIERS);
Geremy Condraf1bcca82013-01-07 22:35:24 -08009423 } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
9424 dumpState.setDump(DumpState.DUMP_KEYSETS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009425 }
9426 }
Kenny Root447106f2011-03-23 11:00:15 -07009427
9428 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 synchronized (mPackages) {
Kenny Root05ca4c92011-09-15 10:36:25 -07009430 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
9431 if (dumpState.onTitlePrinted())
9432 pw.println(" ");
9433 pw.println("Verifiers:");
9434 pw.print(" Required: ");
9435 pw.print(mRequiredVerifierPackage);
9436 pw.print(" (uid=");
Amith Yamasani483f3b02012-03-13 16:08:00 -07009437 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
Kenny Root05ca4c92011-09-15 10:36:25 -07009438 pw.println(")");
9439 }
9440
Kenny Root447106f2011-03-23 11:00:15 -07009441 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
9442 if (dumpState.onTitlePrinted())
9443 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009444 pw.println("Libraries:");
Kenny Root447106f2011-03-23 11:00:15 -07009445 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009446 while (it.hasNext()) {
9447 String name = it.next();
9448 pw.print(" ");
9449 pw.print(name);
9450 pw.print(" -> ");
9451 pw.println(mSharedLibraries.get(name));
9452 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009453 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009454
Kenny Root447106f2011-03-23 11:00:15 -07009455 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
9456 if (dumpState.onTitlePrinted())
9457 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009458 pw.println("Features:");
9459 Iterator<String> it = mAvailableFeatures.keySet().iterator();
9460 while (it.hasNext()) {
9461 String name = it.next();
9462 pw.print(" ");
9463 pw.println(name);
9464 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009465 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009466
Kenny Root447106f2011-03-23 11:00:15 -07009467 if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
9468 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
9469 : "Activity Resolver Table:", " ", packageName,
9470 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
9471 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009472 }
Kenny Root447106f2011-03-23 11:00:15 -07009473 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
9474 : "Receiver Resolver Table:", " ", packageName,
9475 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
9476 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009477 }
Kenny Root447106f2011-03-23 11:00:15 -07009478 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
9479 : "Service Resolver Table:", " ", packageName,
9480 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
9481 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009482 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009483 }
9484
9485 if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
Dianne Hackborn63092712012-10-07 14:45:35 -07009486 for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
9487 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
9488 int user = mSettings.mPreferredActivities.keyAt(i);
9489 if (pir.dump(pw,
9490 dumpState.getTitlePrinted()
9491 ? "\nPreferred Activities User " + user + ":"
9492 : "Preferred Activities User " + user + ":", " ",
9493 packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
9494 dumpState.setTitlePrinted(true);
9495 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009496 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009497 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009498
9499 if (dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
9500 pw.flush();
9501 FileOutputStream fout = new FileOutputStream(fd);
9502 BufferedOutputStream str = new BufferedOutputStream(fout);
9503 XmlSerializer serializer = new FastXmlSerializer();
9504 try {
9505 serializer.setOutput(str, "utf-8");
9506 serializer.startDocument(null, true);
9507 serializer.setFeature(
9508 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -08009509 mSettings.writePreferredActivitiesLPr(serializer, 0, fullPreferred);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07009510 serializer.endDocument();
9511 serializer.flush();
9512 } catch (IllegalArgumentException e) {
9513 pw.println("Failed writing: " + e);
9514 } catch (IllegalStateException e) {
9515 pw.println("Failed writing: " + e);
9516 } catch (IOException e) {
9517 pw.println("Failed writing: " + e);
9518 }
9519 }
9520
Kenny Root447106f2011-03-23 11:00:15 -07009521 if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
9522 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009524
Kenny Root447106f2011-03-23 11:00:15 -07009525 if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
9526 boolean printedSomething = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009527 for (PackageParser.Provider p : mProvidersByComponent.values()) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009528 if (packageName != null && !packageName.equals(p.info.packageName)) {
9529 continue;
9530 }
9531 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -07009532 if (dumpState.onTitlePrinted())
9533 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009534 pw.println("Registered ContentProviders:");
9535 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009536 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009537 pw.print(" "); pw.print(p.getComponentShortName()); pw.println(":");
9538 pw.print(" "); pw.println(p.toString());
9539 }
9540 printedSomething = false;
9541 for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) {
9542 PackageParser.Provider p = entry.getValue();
9543 if (packageName != null && !packageName.equals(p.info.packageName)) {
9544 continue;
9545 }
9546 if (!printedSomething) {
9547 if (dumpState.onTitlePrinted())
9548 pw.println(" ");
9549 pw.println("ContentProvider Authorities:");
9550 printedSomething = true;
9551 }
9552 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
9553 pw.print(" "); pw.println(p.toString());
Kenny Rooteca64b32012-06-25 16:37:32 -07009554 if (p.info != null && p.info.applicationInfo != null) {
9555 final String appInfo = p.info.applicationInfo.toString();
9556 pw.print(" applicationInfo="); pw.println(appInfo);
9557 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009558 }
9559 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08009560
9561 if (dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
9562 if (dumpState.onTitlePrinted()) {
9563 pw.println(" ");
9564 }
9565 mSettings.mKeySetManager.dump(pw);
9566 }
9567
Kenny Root447106f2011-03-23 11:00:15 -07009568 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
9569 mSettings.dumpPackagesLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 }
Kenny Root447106f2011-03-23 11:00:15 -07009571
9572 if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
9573 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009574 }
Kenny Root447106f2011-03-23 11:00:15 -07009575
9576 if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
9577 if (dumpState.onTitlePrinted())
9578 pw.println(" ");
9579 mSettings.dumpReadMessagesLPr(pw, dumpState);
9580
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009581 pw.println(" ");
9582 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -07009583 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08009584 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009585 try {
9586 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -07009587 final int avail = in.available();
9588 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009589 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07009590 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009591 } catch (FileNotFoundException e) {
9592 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08009593 } finally {
9594 if (in != null) {
9595 try {
9596 in.close();
Kenny Root447106f2011-03-23 11:00:15 -07009597 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08009598 }
9599 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009600 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 }
9603 }
9604
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009605 // ------- apps on sdcard specific code -------
9606 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -07009607
Kenny Root305bcbf2010-09-03 07:56:38 -07009608 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -07009609
Kenny Root305bcbf2010-09-03 07:56:38 -07009610 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -07009611
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009612 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009613
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009614 private String getEncryptKey() {
9615 try {
Kenny Root305bcbf2010-09-03 07:56:38 -07009616 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
9617 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009618 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -07009619 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
9620 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009621 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009622 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009623 return null;
9624 }
9625 }
9626 return sdEncKey;
9627 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009628 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009629 return null;
Rich Cannings8d578832010-09-09 15:12:40 -07009630 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -07009631 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -07009632 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009633 }
Rich Cannings8d578832010-09-09 15:12:40 -07009634
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009635 }
9636
Kenny Root447106f2011-03-23 11:00:15 -07009637 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -07009638 int tmpIdx = 1;
9639 String list[] = PackageHelper.getSecureContainerList();
9640 if (list != null) {
9641 for (final String name : list) {
9642 // Ignore null and non-temporary container entries
9643 if (name == null || !name.startsWith(mTempContainerPrefix)) {
9644 continue;
9645 }
9646
9647 String subStr = name.substring(mTempContainerPrefix.length());
9648 try {
9649 int cid = Integer.parseInt(subStr);
9650 if (cid >= tmpIdx) {
9651 tmpIdx = cid + 1;
9652 }
9653 } catch (NumberFormatException e) {
9654 }
9655 }
9656 }
9657 return mTempContainerPrefix + tmpIdx;
9658 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009659
Kenny Root447106f2011-03-23 11:00:15 -07009660 /*
9661 * Update media status on PackageManager.
9662 */
9663 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
9664 int callingUid = Binder.getCallingUid();
9665 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
9666 throw new SecurityException("Media status can only be updated by the system");
9667 }
9668 // reader; this apparently protects mMediaMounted, but should probably
9669 // be a different lock in that case.
9670 synchronized (mPackages) {
9671 Log.i(TAG, "Updating external media status from "
9672 + (mMediaMounted ? "mounted" : "unmounted") + " to "
9673 + (mediaStatus ? "mounted" : "unmounted"));
9674 if (DEBUG_SD_INSTALL)
9675 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
9676 + ", mMediaMounted=" + mMediaMounted);
9677 if (mediaStatus == mMediaMounted) {
9678 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
9679 : 0, -1);
9680 mHandler.sendMessage(msg);
9681 return;
9682 }
9683 mMediaMounted = mediaStatus;
9684 }
9685 // Queue up an async operation since the package installation may take a
9686 // little while.
9687 mHandler.post(new Runnable() {
9688 public void run() {
Kenny Root438a0ef2012-08-09 13:36:16 -07009689 updateExternalMediaStatusInner(mediaStatus, reportStatus, true);
Kenny Root447106f2011-03-23 11:00:15 -07009690 }
9691 });
9692 }
9693
Kenny Root51a573c2012-05-17 13:30:28 -07009694 /**
9695 * Called by MountService when the initial ASECs to scan are available.
9696 * Should block until all the ASEC containers are finished being scanned.
9697 */
9698 public void scanAvailableAsecs() {
Kenny Root438a0ef2012-08-09 13:36:16 -07009699 updateExternalMediaStatusInner(true, false, false);
Kenny Root51a573c2012-05-17 13:30:28 -07009700 }
9701
Kenny Root447106f2011-03-23 11:00:15 -07009702 /*
9703 * Collect information of applications on external media, map them against
9704 * existing containers and update information based on current mount status.
9705 * Please note that we always have to report status if reportStatus has been
9706 * set to true especially when unloading packages.
9707 */
Kenny Root438a0ef2012-08-09 13:36:16 -07009708 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus,
9709 boolean externalStorage) {
Kenny Root447106f2011-03-23 11:00:15 -07009710 // Collection of uids
9711 int uidArr[] = null;
9712 // Collection of stale containers
9713 HashSet<String> removeCids = new HashSet<String>();
9714 // Collection of packages on external media with valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07009715 HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
Kenny Root447106f2011-03-23 11:00:15 -07009716 // Get list of secure containers.
9717 final String list[] = PackageHelper.getSecureContainerList();
9718 if (list == null || list.length == 0) {
9719 Log.i(TAG, "No secure containers on sdcard");
9720 } else {
9721 // Process list of secure containers and categorize them
9722 // as active or stale based on their package internal state.
9723 int uidList[] = new int[list.length];
9724 int num = 0;
9725 // reader
9726 synchronized (mPackages) {
9727 for (String cid : list) {
Kenny Root447106f2011-03-23 11:00:15 -07009728 if (DEBUG_SD_INSTALL)
9729 Log.i(TAG, "Processing container " + cid);
Kenny Rootc7a89992012-06-05 15:13:17 -07009730 String pkgName = getAsecPackageName(cid);
Kenny Root447106f2011-03-23 11:00:15 -07009731 if (pkgName == null) {
9732 if (DEBUG_SD_INSTALL)
9733 Log.i(TAG, "Container : " + cid + " stale");
9734 removeCids.add(cid);
9735 continue;
9736 }
9737 if (DEBUG_SD_INSTALL)
9738 Log.i(TAG, "Looking for pkg : " + pkgName);
Kenny Rootc7a89992012-06-05 15:13:17 -07009739
9740 final PackageSetting ps = mSettings.mPackages.get(pkgName);
9741 if (ps == null) {
9742 Log.i(TAG, "Deleting container with no matching settings " + cid);
9743 removeCids.add(cid);
9744 continue;
9745 }
9746
Kenny Root438a0ef2012-08-09 13:36:16 -07009747 /*
9748 * Skip packages that are not external if we're unmounting
9749 * external storage.
9750 */
9751 if (externalStorage && !isMounted && !isExternal(ps)) {
9752 continue;
9753 }
9754
Kenny Rootc7a89992012-06-05 15:13:17 -07009755 final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
Kenny Root447106f2011-03-23 11:00:15 -07009756 // The package status is changed only if the code path
9757 // matches between settings and the container id.
Kenny Rootc7a89992012-06-05 15:13:17 -07009758 if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
9759 if (DEBUG_SD_INSTALL) {
Kenny Root447106f2011-03-23 11:00:15 -07009760 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
9761 + " at code path: " + ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -07009762 }
9763
Kenny Root447106f2011-03-23 11:00:15 -07009764 // We do have a valid package installed on sdcard
9765 processCids.put(args, ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -07009766 final int uid = ps.appId;
Kenny Root447106f2011-03-23 11:00:15 -07009767 if (uid != -1) {
9768 uidList[num++] = uid;
9769 }
9770 } else {
Kenny Rootc7a89992012-06-05 15:13:17 -07009771 Log.i(TAG, "Deleting stale container for " + cid);
Kenny Root447106f2011-03-23 11:00:15 -07009772 removeCids.add(cid);
9773 }
9774 }
9775 }
9776
9777 if (num > 0) {
9778 // Sort uid list
9779 Arrays.sort(uidList, 0, num);
9780 // Throw away duplicates
9781 uidArr = new int[num];
9782 uidArr[0] = uidList[0];
9783 int di = 0;
9784 for (int i = 1; i < num; i++) {
9785 if (uidList[i - 1] != uidList[i]) {
9786 uidArr[di++] = uidList[i];
9787 }
9788 }
9789 }
9790 }
9791 // Process packages with valid entries.
Kenny Root6dceb882012-04-12 14:23:49 -07009792 if (isMounted) {
Kenny Root447106f2011-03-23 11:00:15 -07009793 if (DEBUG_SD_INSTALL)
9794 Log.i(TAG, "Loading packages");
9795 loadMediaPackages(processCids, uidArr, removeCids);
Jeff Sharkey752cd922012-09-23 16:25:12 -07009796 startCleaningPackages();
Kenny Root447106f2011-03-23 11:00:15 -07009797 } else {
9798 if (DEBUG_SD_INSTALL)
9799 Log.i(TAG, "Unloading packages");
9800 unloadMediaPackages(processCids, uidArr, reportStatus);
9801 }
9802 }
9803
9804 private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList,
9805 int uidArr[], IIntentReceiver finishedReceiver) {
9806 int size = pkgList.size();
9807 if (size > 0) {
9808 // Send broadcasts here
9809 Bundle extras = new Bundle();
9810 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
9811 .toArray(new String[size]));
9812 if (uidArr != null) {
9813 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
9814 }
9815 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
9816 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009817 sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
Kenny Root447106f2011-03-23 11:00:15 -07009818 }
9819 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009820
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009821 /*
Kenny Root447106f2011-03-23 11:00:15 -07009822 * Look at potentially valid container ids from processCids If package
9823 * information doesn't match the one on record or package scanning fails,
9824 * the cid is added to list of removeCids. We currently don't delete stale
9825 * containers.
9826 */
Kenny Root6dceb882012-04-12 14:23:49 -07009827 private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07009828 HashSet<String> removeCids) {
9829 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07009830 Set<AsecInstallArgs> keys = processCids.keySet();
Kenny Root447106f2011-03-23 11:00:15 -07009831 boolean doGc = false;
Kenny Root6dceb882012-04-12 14:23:49 -07009832 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07009833 String codePath = processCids.get(args);
9834 if (DEBUG_SD_INSTALL)
9835 Log.i(TAG, "Loading container : " + args.cid);
9836 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9837 try {
9838 // Make sure there are no container errors first.
9839 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
9840 Slog.e(TAG, "Failed to mount cid : " + args.cid
9841 + " when installing from sdcard");
9842 continue;
9843 }
9844 // Check code path here.
9845 if (codePath == null || !codePath.equals(args.getCodePath())) {
9846 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
9847 + " does not match one in settings " + codePath);
9848 continue;
9849 }
9850 // Parse package
Kenny Root51a573c2012-05-17 13:30:28 -07009851 int parseFlags = mDefParseFlags;
9852 if (args.isExternal()) {
9853 parseFlags |= PackageParser.PARSE_ON_SDCARD;
9854 }
Kenny Rootc7a89992012-06-05 15:13:17 -07009855 if (args.isFwdLocked()) {
9856 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
9857 }
Kenny Root51a573c2012-05-17 13:30:28 -07009858
Kenny Root447106f2011-03-23 11:00:15 -07009859 doGc = true;
9860 synchronized (mInstallLock) {
9861 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009862 0, 0, null);
Kenny Root447106f2011-03-23 11:00:15 -07009863 // Scan the package
9864 if (pkg != null) {
9865 /*
9866 * TODO why is the lock being held? doPostInstall is
9867 * called in other places without the lock. This needs
9868 * to be straightened out.
9869 */
9870 // writer
9871 synchronized (mPackages) {
9872 retCode = PackageManager.INSTALL_SUCCEEDED;
9873 pkgList.add(pkg.packageName);
9874 // Post process args
Kenny Root6dceb882012-04-12 14:23:49 -07009875 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
9876 pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07009877 }
9878 } else {
9879 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
9880 }
9881 }
9882
9883 } finally {
9884 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
9885 // Don't destroy container here. Wait till gc clears things
9886 // up.
9887 removeCids.add(args.cid);
9888 }
9889 }
9890 }
9891 // writer
9892 synchronized (mPackages) {
9893 // If the platform SDK has changed since the last time we booted,
9894 // we need to re-grant app permission to catch any new ones that
9895 // appear. This is really a hack, and means that apps can in some
9896 // cases get permissions that the user didn't initially explicitly
9897 // allow... it would be nice to have some better way to handle
9898 // this situation.
9899 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
9900 if (regrantPermissions)
9901 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
9902 + mSdkVersion + "; regranting permissions for external storage");
9903 mSettings.mExternalSdkPlatform = mSdkVersion;
9904
9905 // Make sure group IDs have been assigned, and any permission
9906 // changes in other apps are accounted for
Dianne Hackborne639da72012-02-21 15:11:13 -08009907 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
9908 | (regrantPermissions
9909 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
9910 : 0));
Kenny Root447106f2011-03-23 11:00:15 -07009911 // can downgrade to reader
9912 // Persist settings
9913 mSettings.writeLPr();
9914 }
9915 // Send a broadcast to let everyone know we are done processing
9916 if (pkgList.size() > 0) {
9917 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
9918 }
9919 // Force gc to avoid any stale parser references that we might have.
9920 if (doGc) {
9921 Runtime.getRuntime().gc();
9922 }
9923 // List stale containers and destroy stale temporary containers.
9924 if (removeCids != null) {
9925 for (String cid : removeCids) {
9926 if (cid.startsWith(mTempContainerPrefix)) {
9927 Log.i(TAG, "Destroying stale temporary container " + cid);
9928 PackageHelper.destroySdDir(cid);
9929 } else {
9930 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009931 }
9932 }
Kenny Root447106f2011-03-23 11:00:15 -07009933 }
9934 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009935
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009936 /*
Kenny Root447106f2011-03-23 11:00:15 -07009937 * Utility method to unload a list of specified containers
9938 */
Kenny Root6dceb882012-04-12 14:23:49 -07009939 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07009940 // Just unmount all valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07009941 for (AsecInstallArgs arg : cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07009942 synchronized (mInstallLock) {
9943 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009944 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009945 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009946 }
9947
Kenny Root447106f2011-03-23 11:00:15 -07009948 /*
9949 * Unload packages mounted on external media. This involves deleting package
9950 * data from internal structures, sending broadcasts about diabled packages,
9951 * gc'ing to free up references, unmounting all secure containers
9952 * corresponding to packages on external media, and posting a
9953 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
9954 * that we always have to post this message if status has been requested no
9955 * matter what.
9956 */
Kenny Root6dceb882012-04-12 14:23:49 -07009957 private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07009958 final boolean reportStatus) {
9959 if (DEBUG_SD_INSTALL)
9960 Log.i(TAG, "unloading media packages");
9961 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07009962 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
9963 final Set<AsecInstallArgs> keys = processCids.keySet();
9964 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07009965 String pkgName = args.getPackageName();
9966 if (DEBUG_SD_INSTALL)
9967 Log.i(TAG, "Trying to unload pkg : " + pkgName);
9968 // Delete package internally
9969 PackageRemovedInfo outInfo = new PackageRemovedInfo();
9970 synchronized (mInstallLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07009971 boolean res = deletePackageLI(pkgName, null, false,
9972 PackageManager.DELETE_KEEP_DATA, outInfo, false);
Kenny Root447106f2011-03-23 11:00:15 -07009973 if (res) {
9974 pkgList.add(pkgName);
9975 } else {
9976 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
9977 failedList.add(args);
9978 }
9979 }
9980 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009981
Kenny Root447106f2011-03-23 11:00:15 -07009982 // reader
9983 synchronized (mPackages) {
9984 // We didn't update the settings after removing each package;
9985 // write them now for all packages.
9986 mSettings.writeLPr();
9987 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009988
Kenny Root447106f2011-03-23 11:00:15 -07009989 // We have to absolutely send UPDATED_MEDIA_STATUS only
9990 // after confirming that all the receivers processed the ordered
9991 // broadcast when packages get disabled, force a gc to clean things up.
9992 // and unload all the containers.
9993 if (pkgList.size() > 0) {
9994 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
9995 public void performReceive(Intent intent, int resultCode, String data,
Dianne Hackborn20e80982012-08-31 19:00:44 -07009996 Bundle extras, boolean ordered, boolean sticky,
9997 int sendingUser) throws RemoteException {
Kenny Root447106f2011-03-23 11:00:15 -07009998 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
9999 reportStatus ? 1 : 0, 1, keys);
10000 mHandler.sendMessage(msg);
10001 }
10002 });
10003 } else {
10004 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
10005 keys);
10006 mHandler.sendMessage(msg);
10007 }
10008 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070010009
Amith Yamasani6ec10122012-08-23 13:49:25 -070010010 /** Binder call */
10011 @Override
Kenny Root447106f2011-03-23 11:00:15 -070010012 public void movePackage(final String packageName, final IPackageMoveObserver observer,
10013 final int flags) {
10014 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
Amith Yamasani6ec10122012-08-23 13:49:25 -070010015 UserHandle user = new UserHandle(UserHandle.getCallingUserId());
Kenny Root447106f2011-03-23 11:00:15 -070010016 int returnCode = PackageManager.MOVE_SUCCEEDED;
10017 int currFlags = 0;
10018 int newFlags = 0;
10019 // reader
10020 synchronized (mPackages) {
10021 PackageParser.Package pkg = mPackages.get(packageName);
10022 if (pkg == null) {
10023 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
10024 } else {
10025 // Disable moving fwd locked apps and system packages
10026 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
10027 Slog.w(TAG, "Cannot move system application");
10028 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root447106f2011-03-23 11:00:15 -070010029 } else if (pkg.mOperationPending) {
10030 Slog.w(TAG, "Attempt to move package which has pending operations");
10031 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
10032 } else {
10033 // Find install location first
10034 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
10035 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
10036 Slog.w(TAG, "Ambigous flags specified for move location.");
10037 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
10038 } else {
10039 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
10040 : PackageManager.INSTALL_INTERNAL;
10041 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
10042 : PackageManager.INSTALL_INTERNAL;
Kenny Rootbf023582012-05-02 16:56:15 -070010043
Kenny Root447106f2011-03-23 11:00:15 -070010044 if (newFlags == currFlags) {
10045 Slog.w(TAG, "No move required. Trying to move to same location");
10046 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Rootbf023582012-05-02 16:56:15 -070010047 } else {
10048 if (isForwardLocked(pkg)) {
10049 currFlags |= PackageManager.INSTALL_FORWARD_LOCK;
10050 newFlags |= PackageManager.INSTALL_FORWARD_LOCK;
10051 }
Kenny Root447106f2011-03-23 11:00:15 -070010052 }
10053 }
10054 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10055 pkg.mOperationPending = true;
10056 }
10057 }
10058 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010059
Kenny Root447106f2011-03-23 11:00:15 -070010060 /*
10061 * TODO this next block probably shouldn't be inside the lock. We
10062 * can't guarantee these won't change after this is fired off
10063 * anyway.
10064 */
10065 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Amith Yamasani6ec10122012-08-23 13:49:25 -070010066 processPendingMove(new MoveParams(null, observer, 0, packageName,
10067 null, -1, user),
Kenny Root6dceb882012-04-12 14:23:49 -070010068 returnCode);
Kenny Root447106f2011-03-23 11:00:15 -070010069 } else {
10070 Message msg = mHandler.obtainMessage(INIT_COPY);
10071 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -070010072 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -070010073 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Amith Yamasani6ec10122012-08-23 13:49:25 -070010074 pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user);
Kenny Root447106f2011-03-23 11:00:15 -070010075 msg.obj = mp;
10076 mHandler.sendMessage(msg);
10077 }
10078 }
10079 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010080
Kenny Root447106f2011-03-23 11:00:15 -070010081 private void processPendingMove(final MoveParams mp, final int currentStatus) {
10082 // Queue up an async operation since the package deletion may take a
10083 // little while.
10084 mHandler.post(new Runnable() {
10085 public void run() {
10086 // TODO fix this; this does nothing.
10087 mHandler.removeCallbacks(this);
10088 int returnCode = currentStatus;
10089 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
10090 int uidArr[] = null;
10091 ArrayList<String> pkgList = null;
10092 synchronized (mPackages) {
10093 PackageParser.Package pkg = mPackages.get(mp.packageName);
10094 if (pkg == null) {
10095 Slog.w(TAG, " Package " + mp.packageName
10096 + " doesn't exist. Aborting move");
10097 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
10098 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
10099 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
10100 + mp.srcArgs.getCodePath() + " to "
10101 + pkg.applicationInfo.sourceDir
10102 + " Aborting move and returning error");
10103 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
10104 } else {
10105 uidArr = new int[] {
10106 pkg.applicationInfo.uid
10107 };
10108 pkgList = new ArrayList<String>();
10109 pkgList.add(mp.packageName);
10110 }
10111 }
10112 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10113 // Send resources unavailable broadcast
10114 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
10115 // Update package code and resource paths
10116 synchronized (mInstallLock) {
10117 synchronized (mPackages) {
10118 PackageParser.Package pkg = mPackages.get(mp.packageName);
10119 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -070010120 if (pkg == null) {
10121 Slog.w(TAG, " Package " + mp.packageName
10122 + " doesn't exist. Aborting move");
10123 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -070010124 } else if (!mp.srcArgs.getCodePath().equals(
10125 pkg.applicationInfo.sourceDir)) {
10126 Slog.w(TAG, "Package " + mp.packageName
10127 + " code path changed from " + mp.srcArgs.getCodePath()
10128 + " to " + pkg.applicationInfo.sourceDir
10129 + " Aborting move and returning error");
10130 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
10131 } else {
10132 final String oldCodePath = pkg.mPath;
10133 final String newCodePath = mp.targetArgs.getCodePath();
10134 final String newResPath = mp.targetArgs.getResourcePath();
10135 final String newNativePath = mp.targetArgs
10136 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -070010137
Kenny Rootddbe50d2012-09-06 13:18:37 -070010138 final File newNativeDir = new File(newNativePath);
Kenny Rootbf023582012-05-02 16:56:15 -070010139
Kenny Rootddbe50d2012-09-06 13:18:37 -070010140 if (!isForwardLocked(pkg) && !isExternal(pkg)) {
Kenny Roota3e90792012-10-18 10:58:36 -070010141 NativeLibraryHelper.copyNativeBinariesIfNeededLI(
10142 new File(newCodePath), newNativeDir);
10143 }
10144 final int[] users = sUserManager.getUserIds();
10145 for (int user : users) {
10146 if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
10147 newNativePath, user) < 0) {
10148 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
Kenny Rootddbe50d2012-09-06 13:18:37 -070010149 }
Kenny Root6a6b0072010-10-07 16:46:10 -070010150 }
10151
10152 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10153 pkg.mPath = newCodePath;
10154 // Move dex files around
10155 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
10156 // Moving of dex files failed. Set
10157 // error code and abort move.
10158 pkg.mPath = pkg.mScanPath;
10159 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10160 }
10161 }
10162
10163 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -070010164 pkg.mScanPath = newCodePath;
10165 pkg.applicationInfo.sourceDir = newCodePath;
10166 pkg.applicationInfo.publicSourceDir = newResPath;
10167 pkg.applicationInfo.nativeLibraryDir = newNativePath;
10168 PackageSetting ps = (PackageSetting) pkg.mExtras;
10169 ps.codePath = new File(pkg.applicationInfo.sourceDir);
10170 ps.codePathString = ps.codePath.getPath();
10171 ps.resourcePath = new File(
10172 pkg.applicationInfo.publicSourceDir);
10173 ps.resourcePathString = ps.resourcePath.getPath();
10174 ps.nativeLibraryPathString = newNativePath;
10175 // Set the application info flag
10176 // correctly.
10177 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
10178 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
10179 } else {
10180 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
10181 }
10182 ps.setFlags(pkg.applicationInfo.flags);
10183 mAppDirs.remove(oldCodePath);
10184 mAppDirs.put(newCodePath, pkg);
10185 // Persist settings
10186 mSettings.writeLPr();
10187 }
10188 }
10189 }
10190 }
10191 // Send resources available broadcast
10192 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
10193 }
10194 }
10195 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
10196 // Clean up failed installation
10197 if (mp.targetArgs != null) {
Kenny Root6dceb882012-04-12 14:23:49 -070010198 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
10199 -1);
Kenny Root447106f2011-03-23 11:00:15 -070010200 }
10201 } else {
10202 // Force a gc to clear things up.
10203 Runtime.getRuntime().gc();
10204 // Delete older code
10205 synchronized (mInstallLock) {
10206 mp.srcArgs.doPostDeleteLI(true);
10207 }
10208 }
Kenny Rootdeb11262010-08-02 11:36:21 -070010209
Kenny Root447106f2011-03-23 11:00:15 -070010210 // Allow more operations on this file if we didn't fail because
10211 // an operation was already pending for this package.
10212 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
10213 synchronized (mPackages) {
10214 PackageParser.Package pkg = mPackages.get(mp.packageName);
10215 if (pkg != null) {
10216 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -070010217 }
10218 }
Kenny Root447106f2011-03-23 11:00:15 -070010219 }
Kenny Rootdeb11262010-08-02 11:36:21 -070010220
Kenny Root447106f2011-03-23 11:00:15 -070010221 IPackageMoveObserver observer = mp.observer;
10222 if (observer != null) {
10223 try {
10224 observer.packageMoved(mp.packageName, returnCode);
10225 } catch (RemoteException e) {
10226 Log.i(TAG, "Observer no longer exists.");
10227 }
10228 }
10229 }
10230 });
10231 }
10232
10233 public boolean setInstallLocation(int loc) {
10234 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
10235 null);
10236 if (getInstallLocation() == loc) {
10237 return true;
10238 }
10239 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
10240 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
Jeff Sharkey625239a2012-09-26 22:03:49 -070010241 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
10242 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION, loc);
Kenny Root447106f2011-03-23 11:00:15 -070010243 return true;
10244 }
10245 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010246 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -070010247
Kenny Root447106f2011-03-23 11:00:15 -070010248 public int getInstallLocation() {
Jeff Sharkey625239a2012-09-26 22:03:49 -070010249 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
10250 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION,
Kenny Root447106f2011-03-23 11:00:15 -070010251 PackageHelper.APP_INSTALL_AUTO);
10252 }
Amith Yamasani0b285492011-04-14 17:35:23 -070010253
Amith Yamasani258848d2012-08-10 17:06:33 -070010254 /** Called by UserManagerService */
Dianne Hackborn4428e172012-08-24 17:43:05 -070010255 void cleanUpUserLILPw(int userHandle) {
Dianne Hackborn4428e172012-08-24 17:43:05 -070010256 if (mDirtyUsers.remove(userHandle));
10257 mSettings.removeUserLPr(userHandle);
10258 if (mInstaller != null) {
10259 // Technically, we shouldn't be doing this with the package lock
10260 // held. However, this is very rare, and there is already so much
10261 // other disk I/O going on, that we'll let it slide for now.
10262 mInstaller.removeUserDataDirs(userHandle);
10263 }
10264 }
10265
10266 /** Called by UserManagerService */
10267 void createNewUserLILPw(int userHandle, File path) {
10268 if (mInstaller != null) {
Dianne Hackborn8a2ed1d2013-01-29 15:18:29 -080010269 mSettings.createNewUserLILPw(this, mInstaller, userHandle, path);
Amith Yamasani13593602012-03-22 16:16:17 -070010270 }
10271 }
10272
Kenny Root0aaa0d92011-09-12 16:42:55 -070010273 @Override
10274 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
10275 mContext.enforceCallingOrSelfPermission(
10276 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
10277 "Only package verification agents can read the verifier device identity");
10278
10279 synchronized (mPackages) {
10280 return mSettings.getVerifierDeviceIdentityLPw();
10281 }
10282 }
Amith Yamasani742a6712011-05-04 14:49:28 -070010283
Amith Yamasani13593602012-03-22 16:16:17 -070010284 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -070010285 public void setPermissionEnforced(String permission, boolean enforced) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010286 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
10287 if (READ_EXTERNAL_STORAGE.equals(permission)) {
10288 synchronized (mPackages) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -070010289 if (mSettings.mReadExternalStorageEnforced == null
10290 || mSettings.mReadExternalStorageEnforced != enforced) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -070010291 mSettings.mReadExternalStorageEnforced = enforced;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010292 mSettings.writeLPr();
Jeff Sharkeyb9a07012012-03-22 17:00:04 -070010293
10294 // kill any non-foreground processes so we restart them and
10295 // grant/revoke the GID.
10296 final IActivityManager am = ActivityManagerNative.getDefault();
10297 if (am != null) {
10298 final long token = Binder.clearCallingIdentity();
10299 try {
10300 am.killProcessesBelowForeground("setPermissionEnforcement");
10301 } catch (RemoteException e) {
10302 } finally {
10303 Binder.restoreCallingIdentity(token);
10304 }
10305 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010306 }
10307 }
10308 } else {
10309 throw new IllegalArgumentException("No selective enforcement for " + permission);
10310 }
10311 }
10312
10313 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -070010314 public boolean isPermissionEnforced(String permission) {
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -070010315 final boolean enforcedDefault = isPermissionEnforcedDefault(permission);
Jeff Sharkey5d32e772012-04-12 15:59:23 -070010316 synchronized (mPackages) {
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -070010317 return isPermissionEnforcedLocked(permission, enforcedDefault);
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010318 }
10319 }
10320
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -070010321 /**
10322 * Check if given permission should be enforced by default. Should always be
10323 * called outside of {@link #mPackages} lock.
10324 */
10325 private boolean isPermissionEnforcedDefault(String permission) {
10326 if (READ_EXTERNAL_STORAGE.equals(permission)) {
Jeff Sharkey625239a2012-09-26 22:03:49 -070010327 return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
10328 android.provider.Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0)
10329 != 0;
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -070010330 } else {
10331 return true;
10332 }
10333 }
10334
10335 /**
10336 * Check if user has requested that given permission be enforced, using
10337 * given default if undefined.
10338 */
10339 private boolean isPermissionEnforcedLocked(String permission, boolean enforcedDefault) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010340 if (READ_EXTERNAL_STORAGE.equals(permission)) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -070010341 if (mSettings.mReadExternalStorageEnforced != null) {
10342 return mSettings.mReadExternalStorageEnforced;
10343 } else {
Jeff Sharkeyc50f31d2012-09-22 17:14:02 -070010344 // User hasn't defined; fall back to secure default
10345 return enforcedDefault;
Jeff Sharkeyf5385772012-05-11 14:04:41 -070010346 }
Jeff Sharkey5d32e772012-04-12 15:59:23 -070010347 } else {
10348 return true;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010349 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -070010350 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -070010351
10352 public boolean isStorageLow() {
10353 final long token = Binder.clearCallingIdentity();
10354 try {
10355 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
10356 .getService(DeviceStorageMonitorService.SERVICE);
10357 return dsm.isMemoryLow();
10358 } finally {
10359 Binder.restoreCallingIdentity(token);
10360 }
10361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362}