blob: 180081b26ebb80317dfcb581e57096be3e374cf0 [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 Hackborn0ac30312011-06-17 14:49:23 -070023import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
Kenny Root27989422011-02-23 16:28:26 -080024import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Jeff Sharkey854b2b12012-04-13 16:03:40 -070025import static com.android.internal.util.ArrayUtils.appendInt;
26import static com.android.internal.util.ArrayUtils.removeInt;
Kenny Root66269ea2011-07-12 14:14:01 -070027import static libcore.io.OsConstants.S_ISLNK;
Kenny Root27989422011-02-23 16:28:26 -080028
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080029import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import com.android.internal.app.ResolverActivity;
Kenny Root85387d72010-08-26 10:13:11 -070031import com.android.internal.content.NativeLibraryHelper;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080032import com.android.internal.content.PackageHelper;
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070033import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080034import com.android.internal.util.XmlUtils;
Kenny Rootcf0b38c2011-03-22 14:17:59 -070035import com.android.server.DeviceStorageMonitorService;
36import com.android.server.EventLogTags;
37import com.android.server.IntentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
Jason parksa3cdaa52011-01-13 14:15:43 -060039import org.xmlpull.v1.XmlPullParser;
40import org.xmlpull.v1.XmlPullParserException;
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -070041import org.xmlpull.v1.XmlSerializer;
Jason parksa3cdaa52011-01-13 14:15:43 -060042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.app.ActivityManagerNative;
44import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080045import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080046import android.app.backup.IBackupManager;
Kenny Root5ab21572011-07-27 11:11:19 -070047import android.content.BroadcastReceiver;
Jason parksa3cdaa52011-01-13 14:15:43 -060048import android.content.ComponentName;
Kenny Root27989422011-02-23 16:28:26 -080049import android.content.Context;
Dianne Hackbornecb0e632010-04-07 20:22:55 -070050import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.Intent;
52import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070053import android.content.IntentSender;
Jason parks1125d782011-01-12 09:47:26 -060054import android.content.ServiceConnection;
Jason parksa3cdaa52011-01-13 14:15:43 -060055import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.pm.ActivityInfo;
57import android.content.pm.ApplicationInfo;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070058import android.content.pm.ContainerEncryptionParams;
Dianne Hackborn49237342009-08-27 20:08:01 -070059import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.IPackageDataObserver;
61import android.content.pm.IPackageDeleteObserver;
62import android.content.pm.IPackageInstallObserver;
63import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080064import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.IPackageStatsObserver;
66import android.content.pm.InstrumentationInfo;
67import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080068import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.PackageManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060070import android.content.pm.PackageParser;
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -070071import android.content.pm.PackageParser.ActivityIntentInfo;
Kenny Root27989422011-02-23 16:28:26 -080072import android.content.pm.PackageStats;
Kenny Root0e2c0f32011-04-15 17:50:10 -070073import android.content.pm.ParceledListSlice;
Jason parksa3cdaa52011-01-13 14:15:43 -060074import android.content.pm.PermissionGroupInfo;
Kenny Root27989422011-02-23 16:28:26 -080075import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.pm.ProviderInfo;
77import android.content.pm.ResolveInfo;
78import android.content.pm.ServiceInfo;
79import android.content.pm.Signature;
Amith Yamasani0b285492011-04-14 17:35:23 -070080import android.content.pm.UserInfo;
Kenny Root5ab21572011-07-27 11:11:19 -070081import android.content.pm.ManifestDigest;
Kenny Root0aaa0d92011-09-12 16:42:55 -070082import android.content.pm.VerifierDeviceIdentity;
Kenny Root05ca4c92011-09-15 10:36:25 -070083import android.content.pm.VerifierInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.net.Uri;
85import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070086import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Bundle;
Kenny Root27989422011-02-23 16:28:26 -080088import android.os.Environment;
89import android.os.FileObserver;
90import android.os.FileUtils;
91import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080093import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070094import android.os.Looper;
95import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.ParcelFileDescriptor;
98import android.os.Process;
Kenny Root27989422011-02-23 16:28:26 -080099import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.ServiceManager;
101import android.os.SystemClock;
102import android.os.SystemProperties;
Amith Yamasani742a6712011-05-04 14:49:28 -0700103import android.os.UserId;
Jeff Sharkeyf5385772012-05-11 14:04:41 -0700104import android.provider.Settings.Secure;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800105import android.security.SystemKeyStore;
Kenny Root27989422011-02-23 16:28:26 -0800106import android.util.DisplayMetrics;
107import android.util.EventLog;
108import android.util.Log;
109import android.util.LogPrinter;
110import android.util.Slog;
111import android.util.SparseArray;
112import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import android.view.Display;
114import android.view.WindowManager;
115
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -0700116import java.io.BufferedOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.File;
118import java.io.FileDescriptor;
119import java.io.FileInputStream;
120import java.io.FileNotFoundException;
121import java.io.FileOutputStream;
122import java.io.FileReader;
123import java.io.FilenameFilter;
124import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800126import java.security.NoSuchAlgorithmException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700127import java.security.PublicKey;
128import java.security.cert.CertificateException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800129import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130import java.util.ArrayList;
131import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700132import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.Collections;
134import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800135import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136import java.util.HashMap;
137import java.util.HashSet;
138import java.util.Iterator;
139import java.util.List;
140import java.util.Map;
Amith Yamasani13593602012-03-22 16:16:17 -0700141import java.util.Map.Entry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143
Kenny Root66269ea2011-07-12 14:14:01 -0700144import libcore.io.ErrnoException;
Kenny Root3f99afc2012-04-14 10:13:10 -0700145import libcore.io.IoUtils;
Kenny Root66269ea2011-07-12 14:14:01 -0700146import libcore.io.Libcore;
147
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700148/**
149 * Keep track of all those .apks everywhere.
150 *
151 * This is very central to the platform's security; please run the unit
152 * tests whenever making modifications here:
153 *
154mmm frameworks/base/tests/AndroidTests
155adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
156adb 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 -0700157 *
158 * {@hide}
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700159 */
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700160public class PackageManagerService extends IPackageManager.Stub {
161 static final String TAG = "PackageManager";
162 static final boolean DEBUG_SETTINGS = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 private static final boolean DEBUG_PREFERRED = false;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700164 static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800165 private static final boolean DEBUG_INSTALL = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800166 private static final boolean DEBUG_REMOVE = false;
167 private static final boolean DEBUG_SHOW_INFO = false;
168 private static final boolean DEBUG_PACKAGE_INFO = false;
169 private static final boolean DEBUG_INTENT_MATCHING = false;
170 private static final boolean DEBUG_PACKAGE_SCANNING = false;
171 private static final boolean DEBUG_APP_DIR_OBSERVER = false;
Kenny Root05ca4c92011-09-15 10:36:25 -0700172 private static final boolean DEBUG_VERIFY = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400175 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700176 private static final int NFC_UID = Process.NFC_UID;
Jaikumar Ganesh1abb1cb2012-01-25 16:14:50 -0800177 private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 private static final boolean GET_CERTIFICATES = true;
180
181 private static final int REMOVE_EVENTS =
182 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
183 private static final int ADD_EVENTS =
184 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
185
186 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800187 // Suffix used during package installation when copying/moving
188 // package apks to install directory.
189 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190
191 static final int SCAN_MONITOR = 1<<0;
192 static final int SCAN_NO_DEX = 1<<1;
193 static final int SCAN_FORCE_DEX = 1<<2;
194 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800195 static final int SCAN_NEW_INSTALL = 1<<4;
196 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700197 static final int SCAN_UPDATE_TIME = 1<<6;
Dianne Hackborn661cd522011-08-22 00:26:20 -0700198 static final int SCAN_DEFER_DEX = 1<<7;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -0700199 static final int SCAN_BOOTING = 1<<8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700201 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700202
Kenny Root5ab21572011-07-27 11:11:19 -0700203 /**
204 * Whether verification is enabled by default.
205 */
Brett Chabotae05e862011-08-24 18:38:26 -0700206 // STOPSHIP: change this to true
207 private static final boolean DEFAULT_VERIFY_ENABLE = false;
Kenny Root5ab21572011-07-27 11:11:19 -0700208
209 /**
210 * The default maximum time to wait for the verification agent to return in
211 * milliseconds.
212 */
rich canningsaa8513e2012-05-21 16:15:23 -0700213 private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
Kenny Root5ab21572011-07-27 11:11:19 -0700214
rich canningsa6cfe522012-05-21 15:50:56 -0700215 /**
216 * The default response for package verification timeout.
217 *
218 * This can be either PackageManager.VERIFICATION_ALLOW or
219 * PackageManager.VERIFICATION_REJECT.
220 */
221 private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
222
Kenny Root11128572010-10-11 10:51:32 -0700223 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
224
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800225 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700226 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800227 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700228
Kenny Root05ca4c92011-09-15 10:36:25 -0700229 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
230
Kenny Root85387d72010-08-26 10:13:11 -0700231 private static final String LIB_DIR_NAME = "lib";
232
Kenny Rootc78a8072010-07-27 15:18:38 -0700233 static final String mTempContainerPrefix = "smdl2tmp";
234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
236 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700237 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238
Dianne Hackborn851a5412009-05-08 12:06:44 -0700239 final int mSdkVersion = Build.VERSION.SDK_INT;
240 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
241 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 final Context mContext;
244 final boolean mFactoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700245 final boolean mOnlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700246 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 final DisplayMetrics mMetrics;
248 final int mDefParseFlags;
249 final String[] mSeparateProcesses;
250
251 // This is where all application persistent data goes.
252 final File mAppDataDir;
253
Amith Yamasani0b285492011-04-14 17:35:23 -0700254 // This is where all application persistent data goes for secondary users.
255 final File mUserAppDataDir;
256
Kenny Root51a573c2012-05-17 13:30:28 -0700257 /** The location for ASEC container files on internal storage. */
258 final String mAsecInternalPath;
259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 // This is the object monitoring the framework dir.
261 final FileObserver mFrameworkInstallObserver;
262
263 // This is the object monitoring the system app dir.
264 final FileObserver mSystemInstallObserver;
265
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700266 // This is the object monitoring the system app dir.
267 final FileObserver mVendorInstallObserver;
268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 // This is the object monitoring mAppInstallDir.
270 final FileObserver mAppInstallObserver;
271
272 // This is the object monitoring mDrmAppPrivateInstallDir.
273 final FileObserver mDrmAppInstallObserver;
274
275 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
276 // LOCK HELD. Can be called with mInstallLock held.
277 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 final File mFrameworkDir;
280 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700281 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700283 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
286 // apps.
287 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 // Lock for state used when installing and doing other long running
292 // operations. Methods that must be called with this lock held have
293 // the prefix "LI".
294 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 // These are the directories in the 3rd party applications installed dir
297 // that we have currently loaded packages from. Keys are the application's
298 // installed zip file (absolute codePath), and values are Package.
299 final HashMap<String, PackageParser.Package> mAppDirs =
300 new HashMap<String, PackageParser.Package>();
301
302 // Information for the parser to write more useful error messages.
303 File mScanningPath;
304 int mLastScanError;
305
306 final int[] mOutPermissions = new int[3];
307
308 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 // Keys are String (package name), values are Package. This also serves
311 // as the lock for the global state. Methods that must be called with
312 // this lock held have the prefix "LP".
313 final HashMap<String, PackageParser.Package> mPackages =
314 new HashMap<String, PackageParser.Package>();
315
316 final Settings mSettings;
317 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318
319 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
320 int[] mGlobalGids;
321
322 // These are the built-in uid -> permission mappings that were read from the
323 // etc/permissions.xml file.
324 final SparseArray<HashSet<String>> mSystemPermissions =
325 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 // These are the built-in shared libraries that were read from the
328 // etc/permissions.xml file.
329 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800330
Dianne Hackborn49237342009-08-27 20:08:01 -0700331 // Temporary for building the final shared libraries for an .apk.
332 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800333
Dianne Hackborn49237342009-08-27 20:08:01 -0700334 // These are the features this devices supports that were read from the
335 // etc/permissions.xml file.
336 final HashMap<String, FeatureInfo> mAvailableFeatures =
337 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 // All available activities, for your resolving pleasure.
340 final ActivityIntentResolver mActivities =
341 new ActivityIntentResolver();
342
343 // All available receivers, for your resolving pleasure.
344 final ActivityIntentResolver mReceivers =
345 new ActivityIntentResolver();
346
347 // All available services, for your resolving pleasure.
348 final ServiceIntentResolver mServices = new ServiceIntentResolver();
349
350 // Keys are String (provider class name), values are Provider.
351 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
352 new HashMap<ComponentName, PackageParser.Provider>();
353
354 // Mapping from provider base names (first directory in content URI codePath)
355 // to the provider information.
356 final HashMap<String, PackageParser.Provider> mProviders =
357 new HashMap<String, PackageParser.Provider>();
358
359 // Mapping from instrumentation class names to info about them.
360 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
361 new HashMap<ComponentName, PackageParser.Instrumentation>();
362
363 // Mapping from permission names to info about them.
364 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
365 new HashMap<String, PackageParser.PermissionGroup>();
366
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800367 // Packages whose data we have transfered into another package, thus
368 // should no longer exist.
369 final HashSet<String> mTransferedPackages = new HashSet<String>();
370
Dianne Hackborn854060af2009-07-09 18:14:31 -0700371 // Broadcast actions that are only available to the system.
372 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800373
Kenny Root5ab21572011-07-27 11:11:19 -0700374 /** List of packages waiting for verification. */
Kenny Root05ca4c92011-09-15 10:36:25 -0700375 final SparseArray<PackageVerificationState> mPendingVerification
376 = new SparseArray<PackageVerificationState>();
Kenny Root5ab21572011-07-27 11:11:19 -0700377
Dianne Hackborn661cd522011-08-22 00:26:20 -0700378 final ArrayList<PackageParser.Package> mDeferredDexOpt =
379 new ArrayList<PackageParser.Package>();
380
Kenny Root5ab21572011-07-27 11:11:19 -0700381 /** Token for keys in mPendingVerification. */
382 private int mPendingVerificationToken = 0;
383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 boolean mSystemReady;
385 boolean mSafeMode;
386 boolean mHasSystemUidErrors;
387
388 ApplicationInfo mAndroidApplication;
389 final ActivityInfo mResolveActivity = new ActivityInfo();
390 final ResolveInfo mResolveInfo = new ResolveInfo();
391 ComponentName mResolveComponentName;
392 PackageParser.Package mPlatformPackage;
393
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700394 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800395 final HashMap<String, ArrayList<String>> mPendingBroadcasts
396 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800397 // Service Connection to remote media container service to copy
398 // package uri's from external media onto secure containers
399 // or internal storage.
400 private IMediaContainerService mContainerService = null;
401
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700402 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800403 static final int MCS_BOUND = 3;
404 static final int END_COPY = 4;
405 static final int INIT_COPY = 5;
406 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800407 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800408 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800409 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800410 static final int MCS_RECONNECT = 10;
411 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700412 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700413 static final int WRITE_SETTINGS = 13;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700414 static final int WRITE_PACKAGE_RESTRICTIONS = 14;
Kenny Root5ab21572011-07-27 11:11:19 -0700415 static final int PACKAGE_VERIFIED = 15;
416 static final int CHECK_PENDING_VERIFICATION = 16;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700417
418 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800419
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700420 // Delay time in millisecs
421 static final int BROADCAST_DELAY = 10 * 1000;
Kenny Root9718cf52011-02-23 16:45:26 -0800422
Amith Yamasani13593602012-03-22 16:16:17 -0700423 static UserManager sUserManager;
Amith Yamasani0b285492011-04-14 17:35:23 -0700424
Amith Yamasani483f3b02012-03-13 16:08:00 -0700425 // Stores a list of users whose package restrictions file needs to be updated
426 private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
427
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800428 final private DefaultContainerConnection mDefContainerConn =
429 new DefaultContainerConnection();
430 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800431 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800432 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800433 IMediaContainerService imcs =
434 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800435 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800436 }
437
438 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800439 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800440 }
441 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700442
Christopher Tate1bb69062010-02-19 17:02:12 -0800443 // Recordkeeping of restore-after-install operations that are currently in flight
444 // between the Package Manager and the Backup Manager
445 class PostInstallData {
446 public InstallArgs args;
447 public PackageInstalledInfo res;
448
449 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
450 args = _a;
451 res = _r;
452 }
453 };
454 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
455 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
456
Kenny Root05ca4c92011-09-15 10:36:25 -0700457 private final String mRequiredVerifierPackage;
458
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700459 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800460 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800461 final ArrayList<HandlerParams> mPendingInstalls =
462 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800463
464 private boolean connectToService() {
465 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
466 " DefaultContainerService");
467 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700468 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800469 if (mContext.bindService(service, mDefContainerConn,
470 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700471 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800472 mBound = true;
473 return true;
474 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700475 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800476 return false;
477 }
478
479 private void disconnectService() {
480 mContainerService = null;
481 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700482 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800483 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700484 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800485 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800486
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700487 PackageHandler(Looper looper) {
488 super(looper);
489 }
Dianne Hackborn7d608422011-08-07 16:24:18 -0700490
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700491 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700492 try {
493 doHandleMessage(msg);
494 } finally {
495 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
496 }
497 }
498
499 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700500 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800501 case INIT_COPY: {
Kenny Root5ab21572011-07-27 11:11:19 -0700502 if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800503 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800504 int idx = mPendingInstalls.size();
Kenny Root5ab21572011-07-27 11:11:19 -0700505 if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800506 // If a bind was already initiated we dont really
507 // need to do anything. The pending install
508 // will be processed later on.
509 if (!mBound) {
510 // If this is the only one pending we might
511 // have to bind to the service again.
512 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800513 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800514 params.serviceError();
515 return;
516 } else {
517 // Once we bind to the service, the first
518 // pending request will be processed.
519 mPendingInstalls.add(idx, params);
520 }
521 } else {
522 mPendingInstalls.add(idx, params);
523 // Already bound to the service. Just make
524 // sure we trigger off processing the first request.
525 if (idx == 0) {
526 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800527 }
528 }
529 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800530 }
531 case MCS_BOUND: {
Kenny Root5ab21572011-07-27 11:11:19 -0700532 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800533 if (msg.obj != null) {
534 mContainerService = (IMediaContainerService) msg.obj;
535 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800536 if (mContainerService == null) {
537 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800538 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800539 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800540 // Indicate service bind error
541 params.serviceError();
542 }
543 mPendingInstalls.clear();
544 } else if (mPendingInstalls.size() > 0) {
545 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800546 if (params != null) {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700547 if (params.startCopy()) {
548 // We are done... look for more work or to
549 // go idle.
550 if (DEBUG_SD_INSTALL) Log.i(TAG,
551 "Checking for more work or unbind...");
552 // Delete pending install
553 if (mPendingInstalls.size() > 0) {
554 mPendingInstalls.remove(0);
555 }
556 if (mPendingInstalls.size() == 0) {
557 if (mBound) {
558 if (DEBUG_SD_INSTALL) Log.i(TAG,
559 "Posting delayed MCS_UNBIND");
560 removeMessages(MCS_UNBIND);
561 Message ubmsg = obtainMessage(MCS_UNBIND);
562 // Unbind after a little delay, to avoid
563 // continual thrashing.
564 sendMessageDelayed(ubmsg, 10000);
565 }
566 } else {
567 // There are more pending requests in queue.
568 // Just post MCS_BOUND message to trigger processing
569 // of next pending install.
570 if (DEBUG_SD_INSTALL) Log.i(TAG,
571 "Posting MCS_BOUND for next woek");
572 mHandler.sendEmptyMessage(MCS_BOUND);
573 }
574 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800575 }
576 } else {
577 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800578 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800579 }
580 break;
581 }
Kenny Root5ab21572011-07-27 11:11:19 -0700582 case MCS_RECONNECT: {
583 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800584 if (mPendingInstalls.size() > 0) {
585 if (mBound) {
586 disconnectService();
587 }
588 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800589 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800590 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800591 // Indicate service bind error
592 params.serviceError();
593 }
594 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800595 }
596 }
597 break;
598 }
Kenny Root5ab21572011-07-27 11:11:19 -0700599 case MCS_UNBIND: {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700600 // If there is no actual work left, then time to unbind.
Kenny Root5ab21572011-07-27 11:11:19 -0700601 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
602
603 if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800604 if (mBound) {
Kenny Root5ab21572011-07-27 11:11:19 -0700605 if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
606
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800607 disconnectService();
608 }
Kenny Root5ab21572011-07-27 11:11:19 -0700609 } else if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800610 // There are more pending requests in queue.
611 // Just post MCS_BOUND message to trigger processing
612 // of next pending install.
613 mHandler.sendEmptyMessage(MCS_BOUND);
614 }
Kenny Root5ab21572011-07-27 11:11:19 -0700615
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800616 break;
617 }
618 case MCS_GIVE_UP: {
Kenny Root5ab21572011-07-27 11:11:19 -0700619 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
Kenny Root60f7ad82011-03-22 12:49:06 -0700620 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800621 break;
622 }
Kenny Root5ab21572011-07-27 11:11:19 -0700623 case SEND_PENDING_BROADCAST: {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800624 String packages[];
Kenny Root60f7ad82011-03-22 12:49:06 -0700625 ArrayList<String> components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700626 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700627 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700628 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700629 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800630 if (mPendingBroadcasts == null) {
631 return;
632 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700633 size = mPendingBroadcasts.size();
634 if (size <= 0) {
635 // Nothing to be done. Just return
636 return;
637 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800638 packages = new String[size];
639 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700640 uids = new int[size];
Andy McFadden2f362292012-01-20 14:43:38 -0800641 Iterator<Map.Entry<String, ArrayList<String>>>
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800642 it = mPendingBroadcasts.entrySet().iterator();
643 int i = 0;
644 while (it.hasNext() && i < size) {
Andy McFadden2f362292012-01-20 14:43:38 -0800645 Map.Entry<String, ArrayList<String>> ent = it.next();
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800646 packages[i] = ent.getKey();
647 components[i] = ent.getValue();
648 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -0700649 uids[i] = (ps != null) ? ps.appId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800650 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700651 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800652 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700653 mPendingBroadcasts.clear();
654 }
655 // Send broadcasts
656 for (int i = 0; i < size; i++) {
Kenny Root60f7ad82011-03-22 12:49:06 -0700657 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700658 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700659 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700660 break;
661 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800662 case START_CLEANING_PACKAGE: {
663 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700664 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800665 synchronized (mPackages) {
666 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
667 mSettings.mPackagesToBeCleaned.add(packageName);
668 }
669 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700670 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800671 startCleaningPackages();
672 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800673 case POST_INSTALL: {
674 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
675 PostInstallData data = mRunningInstalls.get(msg.arg1);
676 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700677 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800678
679 if (data != null) {
680 InstallArgs args = data.args;
681 PackageInstalledInfo res = data.res;
682
683 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700684 res.removedInfo.sendBroadcast(false, true);
Christopher Tate1bb69062010-02-19 17:02:12 -0800685 Bundle extras = new Bundle(1);
686 extras.putInt(Intent.EXTRA_UID, res.uid);
687 final boolean update = res.removedInfo.removedPackage != null;
688 if (update) {
689 extras.putBoolean(Intent.EXTRA_REPLACING, true);
690 }
691 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
692 res.pkg.applicationInfo.packageName,
Amith Yamasani13593602012-03-22 16:16:17 -0700693 extras, null, null, UserId.USER_ALL);
Christopher Tate1bb69062010-02-19 17:02:12 -0800694 if (update) {
695 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
696 res.pkg.applicationInfo.packageName,
Amith Yamasani13593602012-03-22 16:16:17 -0700697 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800698 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
699 null, null,
Amith Yamasani13593602012-03-22 16:16:17 -0700700 res.pkg.applicationInfo.packageName, null,
701 UserId.USER_ALL);
Christopher Tate1bb69062010-02-19 17:02:12 -0800702 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700703 if (res.removedInfo.args != null) {
704 // Remove the replaced package's older resources safely now
705 deleteOld = true;
706 }
Matt Finifterf8a98ed2012-05-14 15:43:34 -0700707
708 // Log current value of "unknown sources" setting
709 EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
710 getUnknownSourcesSettings());
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700711 }
712 // Force a gc to clear up things
713 Runtime.getRuntime().gc();
714 // We delete after a gc for applications on sdcard.
715 if (deleteOld) {
716 synchronized (mInstallLock) {
717 res.removedInfo.args.doPostDeleteLI(true);
718 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800719 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800720 if (args.observer != null) {
721 try {
722 args.observer.packageInstalled(res.name, res.returnCode);
723 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800724 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800725 }
726 }
727 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800728 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800729 }
730 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700731 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700732 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
733 boolean reportStatus = msg.arg1 == 1;
734 boolean doGc = msg.arg2 == 1;
735 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
736 if (doGc) {
737 // Force a gc to clear up stale containers.
738 Runtime.getRuntime().gc();
739 }
740 if (msg.obj != null) {
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700741 @SuppressWarnings("unchecked")
Kenny Root6dceb882012-04-12 14:23:49 -0700742 Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700743 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
744 // Unload containers
745 unloadAllContainers(args);
746 }
747 if (reportStatus) {
748 try {
749 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
750 PackageHelper.getMountService().finishMediaUpdate();
751 } catch (RemoteException e) {
752 Log.e(TAG, "MountService not running?");
753 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700754 }
755 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700756 case WRITE_SETTINGS: {
757 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
758 synchronized (mPackages) {
759 removeMessages(WRITE_SETTINGS);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700760 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
Kenny Root447106f2011-03-23 11:00:15 -0700761 mSettings.writeLPr();
Amith Yamasani483f3b02012-03-13 16:08:00 -0700762 mDirtyUsers.clear();
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700763 }
764 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
765 } break;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700766 case WRITE_PACKAGE_RESTRICTIONS: {
Dianne Hackborne7f97212011-02-24 14:40:20 -0800767 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
768 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -0700769 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
770 for (int userId : mDirtyUsers) {
771 mSettings.writePackageRestrictionsLPr(userId);
772 }
773 mDirtyUsers.clear();
Dianne Hackborne7f97212011-02-24 14:40:20 -0800774 }
775 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
776 } break;
Kenny Root5ab21572011-07-27 11:11:19 -0700777 case CHECK_PENDING_VERIFICATION: {
778 final int verificationId = msg.arg1;
Kenny Root05ca4c92011-09-15 10:36:25 -0700779 final PackageVerificationState state = mPendingVerification.get(verificationId);
Kenny Root5ab21572011-07-27 11:11:19 -0700780
Kenny Root05ca4c92011-09-15 10:36:25 -0700781 if (state != null) {
782 final InstallArgs args = state.getInstallArgs();
Kenny Roota503a0f2011-10-03 14:45:28 -0700783 Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
Kenny Root5ab21572011-07-27 11:11:19 -0700784 mPendingVerification.remove(verificationId);
785
rich canningsa6cfe522012-05-21 15:50:56 -0700786 int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
787
788 if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
789 Slog.i(TAG, "Continuing with installation of " + args.packageURI.toString());
790 state.setVerifierResponse(Binder.getCallingUid(), PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
791 try {
792 ret = args.copyApk(mContainerService, true);
793 } catch (RemoteException e) {
794 Slog.e(TAG, "Could not contact the ContainerService");
795 }
796 }
797
Kenny Root5ab21572011-07-27 11:11:19 -0700798 processPendingInstall(args, ret);
799
800 mHandler.sendEmptyMessage(MCS_UNBIND);
801 }
802
803 break;
804 }
805 case PACKAGE_VERIFIED: {
806 final int verificationId = msg.arg1;
Kenny Root5ab21572011-07-27 11:11:19 -0700807
Kenny Root05ca4c92011-09-15 10:36:25 -0700808 final PackageVerificationState state = mPendingVerification.get(verificationId);
809 if (state == null) {
Kenny Roota503a0f2011-10-03 14:45:28 -0700810 Slog.w(TAG, "Invalid verification token " + verificationId + " received");
Kenny Root5ab21572011-07-27 11:11:19 -0700811 break;
812 }
813
Kenny Root05ca4c92011-09-15 10:36:25 -0700814 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
Kenny Root5ab21572011-07-27 11:11:19 -0700815
Kenny Root05ca4c92011-09-15 10:36:25 -0700816 state.setVerifierResponse(response.callerUid, response.code);
817
818 if (state.isVerificationComplete()) {
819 mPendingVerification.remove(verificationId);
820
821 final InstallArgs args = state.getInstallArgs();
822
823 int ret;
824 if (state.isInstallAllowed()) {
825 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
826 try {
827 ret = args.copyApk(mContainerService, true);
828 } catch (RemoteException e) {
829 Slog.e(TAG, "Could not contact the ContainerService");
830 }
831 } else {
832 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
Kenny Root5ab21572011-07-27 11:11:19 -0700833 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700834
835 processPendingInstall(args, ret);
836
837 mHandler.sendEmptyMessage(MCS_UNBIND);
Kenny Root5ab21572011-07-27 11:11:19 -0700838 }
839
Kenny Root5ab21572011-07-27 11:11:19 -0700840 break;
841 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700842 }
843 }
844 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800845
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700846 void scheduleWriteSettingsLocked() {
847 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
848 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
849 }
850 }
Amith Yamasani483f3b02012-03-13 16:08:00 -0700851
852 void scheduleWritePackageRestrictionsLocked(int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -0700853 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700854 mDirtyUsers.add(userId);
855 if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
856 mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800857 }
858 }
859
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700860 public static final IPackageManager main(Context context, boolean factoryTest,
861 boolean onlyCore) {
862 PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 ServiceManager.addService("package", m);
864 return m;
865 }
866
867 static String[] splitString(String str, char sep) {
868 int count = 1;
869 int i = 0;
870 while ((i=str.indexOf(sep, i)) >= 0) {
871 count++;
872 i++;
873 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 String[] res = new String[count];
876 i=0;
877 count = 0;
878 int lastI=0;
879 while ((i=str.indexOf(sep, i)) >= 0) {
880 res[count] = str.substring(lastI, i);
881 count++;
882 i++;
883 lastI = i;
884 }
885 res[count] = str.substring(lastI, str.length());
886 return res;
887 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800888
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700889 public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800890 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800894 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 mContext = context;
898 mFactoryTest = factoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700899 mOnlyCore = onlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700900 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 mMetrics = new DisplayMetrics();
902 mSettings = new Settings();
Kenny Root447106f2011-03-23 11:00:15 -0700903 mSettings.addSharedUserLPw("android.uid.system",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
Dianne Hackborn21fbd1f2012-02-10 10:38:10 -0800905 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
906 mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
907 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
Jaikumar Ganesh1abb1cb2012-01-25 16:14:50 -0800908 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909
910 String separateProcesses = SystemProperties.get("debug.separate_processes");
911 if (separateProcesses != null && separateProcesses.length() > 0) {
912 if ("*".equals(separateProcesses)) {
913 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
914 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800915 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 } else {
917 mDefParseFlags = 0;
918 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800919 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 + separateProcesses);
921 }
922 } else {
923 mDefParseFlags = 0;
924 mSeparateProcesses = null;
925 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800926
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700927 mInstaller = new Installer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928
929 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
930 Display d = wm.getDefaultDisplay();
931 d.getMetrics(mMetrics);
932
933 synchronized (mInstallLock) {
Kenny Root447106f2011-03-23 11:00:15 -0700934 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 synchronized (mPackages) {
936 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700937 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 File dataDir = Environment.getDataDirectory();
940 mAppDataDir = new File(dataDir, "data");
Kenny Root51a573c2012-05-17 13:30:28 -0700941 mAsecInternalPath = new File(dataDir, "app-asec").getPath();
Amith Yamasani0b285492011-04-14 17:35:23 -0700942 mUserAppDataDir = new File(dataDir, "user");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
944
Amith Yamasani13593602012-03-22 16:16:17 -0700945 sUserManager = new UserManager(mInstaller, mUserAppDataDir);
Amith Yamasani0b285492011-04-14 17:35:23 -0700946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 readPermissions();
948
Amith Yamasani483f3b02012-03-13 16:08:00 -0700949 mRestoredSettings = mSettings.readLPw(getUsers());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800951
952 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800954
Suchi Amalapurapudaec1722010-01-14 21:25:16 -0800955 // Set flag to monitor and not change apk file paths when
956 // scanning install directories.
Dianne Hackbornd0c5f512012-06-07 16:53:59 -0700957 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700958 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800959 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800960 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700961 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700966 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800967
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700968 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800969
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700970 /**
971 * Out of paranoia, ensure that everything in the boot class
972 * path has been dexed.
973 */
974 String bootClassPath = System.getProperty("java.boot.class.path");
975 if (bootClassPath != null) {
976 String[] paths = splitString(bootClassPath, ':');
977 for (int i=0; i<paths.length; i++) {
978 try {
979 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
980 libFiles.add(paths[i]);
981 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
982 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700984 } catch (FileNotFoundException e) {
985 Slog.w(TAG, "Boot class path not found: " + paths[i]);
986 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -0700987 Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
988 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 }
990 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700991 } else {
992 Slog.w(TAG, "No BOOTCLASSPATH found!");
993 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800994
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700995 /**
996 * Also ensure all external libraries have had dexopt run on them.
997 */
998 if (mSharedLibraries.size() > 0) {
999 Iterator<String> libs = mSharedLibraries.values().iterator();
1000 while (libs.hasNext()) {
1001 String lib = libs.next();
1002 try {
1003 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
1004 libFiles.add(lib);
1005 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
1006 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001008 } catch (FileNotFoundException e) {
1009 Slog.w(TAG, "Library not found: " + lib);
1010 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -07001011 Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
1012 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 }
1014 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001015 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001016
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001017 // Gross hack for now: we know this file doesn't contain any
1018 // code, so don't dexopt it to avoid the resulting log spew.
1019 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
1020
1021 /**
1022 * And there are a number of commands implemented in Java, which
1023 * we currently need to do the dexopt on so that they can be
1024 * run from a non-root shell.
1025 */
1026 String[] frameworkFiles = mFrameworkDir.list();
1027 if (frameworkFiles != null) {
1028 for (int i=0; i<frameworkFiles.length; i++) {
1029 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
1030 String path = libPath.getPath();
1031 // Skip the file if we alrady did it.
1032 if (libFiles.contains(path)) {
1033 continue;
1034 }
1035 // Skip the file if it is not a type we want to dexopt.
1036 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
1037 continue;
1038 }
1039 try {
1040 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
1041 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
1042 didDexOpt = true;
1043 }
1044 } catch (FileNotFoundException e) {
1045 Slog.w(TAG, "Jar not found: " + path);
1046 } catch (IOException e) {
1047 Slog.w(TAG, "Exception reading jar: " + path, e);
1048 }
1049 }
1050 }
1051
1052 if (didDexOpt) {
1053 // If we had to do a dexopt of one of the previous
1054 // things, then something on the system has changed.
1055 // Consider this significant, and wipe away all other
1056 // existing dexopt files to ensure we don't leave any
1057 // dangling around.
1058 String[] files = mDalvikCacheDir.list();
1059 if (files != null) {
1060 for (int i=0; i<files.length; i++) {
1061 String fn = files[i];
1062 if (fn.startsWith("data@app@")
1063 || fn.startsWith("data@app-private@")) {
1064 Slog.i(TAG, "Pruning dalvik file: " + fn);
1065 (new File(mDalvikCacheDir, fn)).delete();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001066 }
1067 }
1068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001070
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001071 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 mFrameworkInstallObserver = new AppDirObserver(
1073 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
1074 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001075 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
1076 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001077 scanMode | SCAN_NO_DEX, 0);
Kenny Root51a573c2012-05-17 13:30:28 -07001078
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001079 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
1081 mSystemInstallObserver = new AppDirObserver(
1082 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
1083 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001084 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001085 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Kenny Root208d3412012-05-07 19:42:35 -07001086
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001087 // Collect all vendor packages.
1088 mVendorAppDir = new File("/vendor/app");
1089 mVendorInstallObserver = new AppDirObserver(
1090 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
1091 mVendorInstallObserver.startWatching();
1092 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001093 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001094
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001095 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1096 mInstaller.moveFiles();
1097
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001098 // Prune any system packages that no longer exist.
Kenny Root87b5d7b2012-05-16 13:36:18 -07001099 final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001100 if (!mOnlyCore) {
1101 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1102 while (psit.hasNext()) {
1103 PackageSetting ps = psit.next();
Kenny Root208d3412012-05-07 19:42:35 -07001104
1105 /*
1106 * If this is not a system app, it can't be a
1107 * disable system app.
1108 */
1109 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1110 continue;
1111 }
1112
1113 /*
1114 * If the package is scanned, it's not erased.
1115 */
Kenny Rooteca64b32012-06-25 16:37:32 -07001116 final PackageParser.Package scannedPkg = mPackages.get(ps.name);
1117 if (scannedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07001118 /*
1119 * If the system app is both scanned and in the
1120 * disabled packages list, then it must have been
1121 * added via OTA. Remove it from the currently
1122 * scanned package so the previously user-installed
1123 * application can be scanned.
1124 */
1125 if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
Kenny Rooteca64b32012-06-25 16:37:32 -07001126 Slog.i(TAG, "Expecting better updatd system app for " + ps.name
1127 + "; removing system app");
1128 removePackageLI(scannedPkg, true);
Kenny Root208d3412012-05-07 19:42:35 -07001129 }
1130
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001131 continue;
1132 }
1133
1134 if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001135 psit.remove();
1136 String msg = "System package " + ps.name
1137 + " no longer exists; wiping its data";
1138 reportSettingsProblem(Log.WARN, msg);
1139 mInstaller.remove(ps.name, 0);
Amith Yamasani13593602012-03-22 16:16:17 -07001140 sUserManager.removePackageForAllUsers(ps.name);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001141 } else {
Kenny Root87b5d7b2012-05-16 13:36:18 -07001142 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
1143 if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
1144 possiblyDeletedUpdatedSystemApps.add(ps.name);
1145 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001146 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001147 }
1148 }
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 mAppInstallDir = new File(dataDir, "app");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 //look for any incomplete package installations
Kenny Root447106f2011-03-23 11:00:15 -07001152 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 //clean up list
1154 for(int i = 0; i < deletePkgsList.size(); i++) {
1155 //clean up here
1156 cleanupInstallFailedPackage(deletePkgsList.get(i));
1157 }
1158 //delete tmp files
1159 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001160
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001161 if (!mOnlyCore) {
1162 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1163 SystemClock.uptimeMillis());
1164 mAppInstallObserver = new AppDirObserver(
1165 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1166 mAppInstallObserver.startWatching();
1167 scanDirLI(mAppInstallDir, 0, scanMode, 0);
1168
1169 mDrmAppInstallObserver = new AppDirObserver(
1170 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1171 mDrmAppInstallObserver.startWatching();
1172 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1173 scanMode, 0);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001174
1175 /**
Kenny Root87b5d7b2012-05-16 13:36:18 -07001176 * Remove disable package settings for any updated system
1177 * apps that were removed via an OTA. If they're not a
1178 * previously-updated app, remove them completely.
1179 * Otherwise, just revoke their system-level permissions.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001180 */
Kenny Root87b5d7b2012-05-16 13:36:18 -07001181 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001182 PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
Kenny Root87b5d7b2012-05-16 13:36:18 -07001183 mSettings.removeDisabledSystemPackageLPw(deletedAppName);
1184
1185 String msg;
1186 if (deletedPkg == null) {
1187 msg = "Updated system package " + deletedAppName
1188 + " no longer exists; wiping its data";
1189
1190 mInstaller.remove(deletedAppName, 0);
1191 sUserManager.removePackageForAllUsers(deletedAppName);
1192 } else {
1193 msg = "Updated system app + " + deletedAppName
1194 + " no longer present; removing system privileges for "
1195 + deletedAppName;
1196
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001197 deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
1198
1199 PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
1200 deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
1201 }
Kenny Root87b5d7b2012-05-16 13:36:18 -07001202 reportSettingsProblem(Log.WARN, msg);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001203 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001204 } else {
1205 mAppInstallObserver = null;
1206 mDrmAppInstallObserver = null;
1207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001209 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001211 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1213 + " seconds");
1214
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001215 // If the platform SDK has changed since the last time we booted,
1216 // we need to re-grant app permission to catch any new ones that
1217 // appear. This is really a hack, and means that apps can in some
1218 // cases get permissions that the user didn't initially explicitly
1219 // allow... it would be nice to have some better way to handle
1220 // this situation.
1221 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1222 != mSdkVersion;
1223 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1224 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1225 + "; regranting permissions for internal storage");
1226 mSettings.mInternalSdkPlatform = mSdkVersion;
1227
Dianne Hackborne639da72012-02-21 15:11:13 -08001228 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
1229 | (regrantPermissions
1230 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
1231 : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232
Dianne Hackborn04505102012-02-29 12:34:04 -08001233 // Verify that all of the preferred activity components actually
1234 // exist. It is possible for applications to be updated and at
1235 // that point remove a previously declared activity component that
1236 // had been set as a preferred activity. We try to clean this up
1237 // the next time we encounter that preferred activity, but it is
1238 // possible for the user flow to never be able to return to that
1239 // situation so here we do a sanity check to make sure we haven't
1240 // left any junk around.
1241 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
1242 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
1243 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
1244 removed.add(pa);
1245 }
1246 }
1247 for (int i=0; i<removed.size(); i++) {
1248 PreferredActivity pa = removed.get(i);
1249 Slog.w(TAG, "Removing dangling preferred activity: "
1250 + pa.mPref.mComponent);
1251 mSettings.mPreferredActivities.removeFilter(pa);
1252 }
1253
Kenny Root447106f2011-03-23 11:00:15 -07001254 // can downgrade to reader
1255 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001257 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 // Now after opening every single application zip, make sure they
1261 // are all flushed. Not really needed, but keeps things nice and
1262 // tidy.
1263 Runtime.getRuntime().gc();
Kenny Root05ca4c92011-09-15 10:36:25 -07001264
1265 mRequiredVerifierPackage = getRequiredVerifierLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 } // synchronized (mPackages)
1267 } // synchronized (mInstallLock)
1268 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001269
Dianne Hackborn58f42a52011-10-10 13:46:34 -07001270 public boolean isFirstBoot() {
1271 return !mRestoredSettings;
1272 }
1273
Kenny Root05ca4c92011-09-15 10:36:25 -07001274 private String getRequiredVerifierLPr() {
1275 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1276 final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
Amith Yamasani483f3b02012-03-13 16:08:00 -07001277 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07001278
1279 String requiredVerifier = null;
1280
1281 final int N = receivers.size();
1282 for (int i = 0; i < N; i++) {
1283 final ResolveInfo info = receivers.get(i);
1284
1285 if (info.activityInfo == null) {
1286 continue;
1287 }
1288
1289 final String packageName = info.activityInfo.packageName;
1290
1291 final PackageSetting ps = mSettings.mPackages.get(packageName);
1292 if (ps == null) {
1293 continue;
1294 }
1295
1296 if (!ps.grantedPermissions
1297 .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
1298 continue;
1299 }
1300
1301 if (requiredVerifier != null) {
1302 throw new RuntimeException("There can be only one required verifier");
1303 }
1304
1305 requiredVerifier = packageName;
1306 }
1307
1308 return requiredVerifier;
1309 }
1310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 @Override
1312 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1313 throws RemoteException {
1314 try {
1315 return super.onTransact(code, data, reply, flags);
1316 } catch (RuntimeException e) {
1317 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001318 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 }
1320 throw e;
1321 }
1322 }
1323
Dianne Hackborne6620b22010-01-22 14:46:21 -08001324 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001325 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001326 int retCode = mInstaller.remove(ps.name, 0);
1327 if (retCode < 0) {
1328 Slog.w(TAG, "Couldn't remove app data directory for package: "
1329 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 } else {
Amith Yamasani13593602012-03-22 16:16:17 -07001331 sUserManager.removePackageForAllUsers(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 }
Dianne Hackborne6620b22010-01-22 14:46:21 -08001333 if (ps.codePath != null) {
1334 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001335 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001336 }
1337 }
1338 if (ps.resourcePath != null) {
1339 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001340 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001341 }
1342 }
Kenny Root447106f2011-03-23 11:00:15 -07001343 mSettings.removePackageLPw(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 }
1345
1346 void readPermissions() {
1347 // Read permissions from .../etc/permission directory.
1348 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1349 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001350 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 return;
1352 }
1353 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001354 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 return;
1356 }
1357
1358 // Iterate over the files in the directory and scan .xml files
1359 for (File f : libraryDir.listFiles()) {
1360 // We'll read platform.xml last
1361 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1362 continue;
1363 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001366 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 continue;
1368 }
1369 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001370 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 continue;
1372 }
1373
1374 readPermissionsFromXml(f);
1375 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1378 final File permFile = new File(Environment.getRootDirectory(),
1379 "etc/permissions/platform.xml");
1380 readPermissionsFromXml(permFile);
1381 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001382
1383 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 FileReader permReader = null;
1385 try {
1386 permReader = new FileReader(permFile);
1387 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001388 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 return;
1390 }
1391
1392 try {
1393 XmlPullParser parser = Xml.newPullParser();
1394 parser.setInput(permReader);
1395
1396 XmlUtils.beginDocument(parser, "permissions");
1397
1398 while (true) {
1399 XmlUtils.nextElement(parser);
1400 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1401 break;
1402 }
1403
1404 String name = parser.getName();
1405 if ("group".equals(name)) {
1406 String gidStr = parser.getAttributeValue(null, "gid");
1407 if (gidStr != null) {
1408 int gid = Integer.parseInt(gidStr);
1409 mGlobalGids = appendInt(mGlobalGids, gid);
1410 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001411 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 + parser.getPositionDescription());
1413 }
1414
1415 XmlUtils.skipCurrentTag(parser);
1416 continue;
1417 } else if ("permission".equals(name)) {
1418 String perm = parser.getAttributeValue(null, "name");
1419 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001420 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 + parser.getPositionDescription());
1422 XmlUtils.skipCurrentTag(parser);
1423 continue;
1424 }
1425 perm = perm.intern();
1426 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 } else if ("assign-permission".equals(name)) {
1429 String perm = parser.getAttributeValue(null, "name");
1430 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001431 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 + parser.getPositionDescription());
1433 XmlUtils.skipCurrentTag(parser);
1434 continue;
1435 }
1436 String uidStr = parser.getAttributeValue(null, "uid");
1437 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001438 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 + parser.getPositionDescription());
1440 XmlUtils.skipCurrentTag(parser);
1441 continue;
1442 }
1443 int uid = Process.getUidForName(uidStr);
1444 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001445 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 + uidStr + "\" at "
1447 + parser.getPositionDescription());
1448 XmlUtils.skipCurrentTag(parser);
1449 continue;
1450 }
1451 perm = perm.intern();
1452 HashSet<String> perms = mSystemPermissions.get(uid);
1453 if (perms == null) {
1454 perms = new HashSet<String>();
1455 mSystemPermissions.put(uid, perms);
1456 }
1457 perms.add(perm);
1458 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 } else if ("library".equals(name)) {
1461 String lname = parser.getAttributeValue(null, "name");
1462 String lfile = parser.getAttributeValue(null, "file");
1463 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001464 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 + parser.getPositionDescription());
1466 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001467 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 + parser.getPositionDescription());
1469 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001470 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001471 mSharedLibraries.put(lname, lfile);
1472 }
1473 XmlUtils.skipCurrentTag(parser);
1474 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001475
Dianne Hackborn49237342009-08-27 20:08:01 -07001476 } else if ("feature".equals(name)) {
1477 String fname = parser.getAttributeValue(null, "name");
1478 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001479 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001480 + parser.getPositionDescription());
1481 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001482 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001483 FeatureInfo fi = new FeatureInfo();
1484 fi.name = fname;
1485 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 }
1487 XmlUtils.skipCurrentTag(parser);
1488 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 } else {
1491 XmlUtils.skipCurrentTag(parser);
1492 continue;
1493 }
1494
1495 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001496 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001498 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001500 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 }
1502 }
1503
1504 void readPermission(XmlPullParser parser, String name)
1505 throws IOException, XmlPullParserException {
1506
1507 name = name.intern();
1508
1509 BasePermission bp = mSettings.mPermissions.get(name);
1510 if (bp == null) {
1511 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1512 mSettings.mPermissions.put(name, bp);
1513 }
1514 int outerDepth = parser.getDepth();
1515 int type;
1516 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1517 && (type != XmlPullParser.END_TAG
1518 || parser.getDepth() > outerDepth)) {
1519 if (type == XmlPullParser.END_TAG
1520 || type == XmlPullParser.TEXT) {
1521 continue;
1522 }
1523
1524 String tagName = parser.getName();
1525 if ("group".equals(tagName)) {
1526 String gidStr = parser.getAttributeValue(null, "gid");
1527 if (gidStr != null) {
1528 int gid = Process.getGidForName(gidStr);
1529 bp.gids = appendInt(bp.gids, gid);
1530 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001531 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 + parser.getPositionDescription());
1533 }
1534 }
1535 XmlUtils.skipCurrentTag(parser);
1536 }
1537 }
1538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 static int[] appendInts(int[] cur, int[] add) {
1540 if (add == null) return cur;
1541 if (cur == null) return add;
1542 final int N = add.length;
1543 for (int i=0; i<N; i++) {
1544 cur = appendInt(cur, add[i]);
1545 }
1546 return cur;
1547 }
1548
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001549 static int[] removeInts(int[] cur, int[] rem) {
1550 if (rem == null) return cur;
1551 if (cur == null) return cur;
1552 final int N = rem.length;
1553 for (int i=0; i<N; i++) {
1554 cur = removeInt(cur, rem[i]);
1555 }
1556 return cur;
1557 }
1558
Amith Yamasani13593602012-03-22 16:16:17 -07001559 PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
1560 if (!sUserManager.exists(userId)) return null;
1561 PackageInfo pi;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001562 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1563 // The package has been uninstalled but has retained data and resources.
Amith Yamasani13593602012-03-22 16:16:17 -07001564 pi = PackageParser.generatePackageInfo(p, null, flags, 0, 0, null, false, 0, userId);
1565 } else {
1566 final PackageSetting ps = (PackageSetting) p.mExtras;
1567 if (ps == null) {
1568 return null;
1569 }
1570 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1571 pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
1572 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
1573 ps.getStopped(userId), ps.getEnabled(userId), userId);
1574 pi.applicationInfo.enabledSetting = ps.getEnabled(userId);
1575 pi.applicationInfo.enabled =
1576 pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
1577 || pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001578 }
Amith Yamasani13593602012-03-22 16:16:17 -07001579 return pi;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 }
1581
Amith Yamasani483f3b02012-03-13 16:08:00 -07001582 @Override
1583 public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001584 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07001585 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 synchronized (mPackages) {
1587 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001588 if (DEBUG_PACKAGE_INFO)
1589 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001591 return generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 }
1593 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001594 return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 }
1596 }
1597 return null;
1598 }
1599
Dianne Hackborn47096932010-02-11 15:57:09 -08001600 public String[] currentToCanonicalPackageNames(String[] names) {
1601 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001602 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001603 synchronized (mPackages) {
1604 for (int i=names.length-1; i>=0; i--) {
1605 PackageSetting ps = mSettings.mPackages.get(names[i]);
1606 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1607 }
1608 }
1609 return out;
1610 }
1611
1612 public String[] canonicalToCurrentPackageNames(String[] names) {
1613 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001614 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001615 synchronized (mPackages) {
1616 for (int i=names.length-1; i>=0; i--) {
1617 String cur = mSettings.mRenamedPackages.get(names[i]);
1618 out[i] = cur != null ? cur : names[i];
1619 }
1620 }
1621 return out;
1622 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07001623
1624 @Override
1625 public int getPackageUid(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001626 if (!sUserManager.exists(userId)) return -1;
Kenny Root447106f2011-03-23 11:00:15 -07001627 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 synchronized (mPackages) {
1629 PackageParser.Package p = mPackages.get(packageName);
1630 if(p != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001631 return UserId.getUid(userId, p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 }
1633 PackageSetting ps = mSettings.mPackages.get(packageName);
1634 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1635 return -1;
1636 }
1637 p = ps.pkg;
Amith Yamasani483f3b02012-03-13 16:08:00 -07001638 return p != null ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 }
1640 }
1641
1642 public int[] getPackageGids(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07001643 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 synchronized (mPackages) {
1645 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001646 if (DEBUG_PACKAGE_INFO)
1647 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 if (p != null) {
1649 final PackageSetting ps = (PackageSetting)p.mExtras;
1650 final SharedUserSetting suid = ps.sharedUser;
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07001651 int[] gids = suid != null ? suid.gids : ps.gids;
1652
1653 // include GIDs for any unenforced permissions
1654 if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
1655 final BasePermission basePerm = mSettings.mPermissions.get(
1656 READ_EXTERNAL_STORAGE);
1657 gids = appendInts(gids, basePerm.gids);
1658 }
1659
1660 return gids;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 }
1662 }
1663 // stupid thing to indicate an error.
1664 return new int[0];
1665 }
1666
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001667 static final PermissionInfo generatePermissionInfo(
1668 BasePermission bp, int flags) {
1669 if (bp.perm != null) {
1670 return PackageParser.generatePermissionInfo(bp.perm, flags);
1671 }
1672 PermissionInfo pi = new PermissionInfo();
1673 pi.name = bp.name;
1674 pi.packageName = bp.sourcePackage;
1675 pi.nonLocalizedLabel = bp.name;
1676 pi.protectionLevel = bp.protectionLevel;
1677 return pi;
1678 }
1679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 public PermissionInfo getPermissionInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001681 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 synchronized (mPackages) {
1683 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001684 if (p != null) {
1685 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 }
1687 return null;
1688 }
1689 }
1690
1691 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001692 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 synchronized (mPackages) {
1694 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1695 for (BasePermission p : mSettings.mPermissions.values()) {
1696 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001697 if (p.perm == null || p.perm.info.group == null) {
1698 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
1700 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001701 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1703 }
1704 }
1705 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 if (out.size() > 0) {
1708 return out;
1709 }
1710 return mPermissionGroups.containsKey(group) ? out : null;
1711 }
1712 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001715 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 synchronized (mPackages) {
1717 return PackageParser.generatePermissionGroupInfo(
1718 mPermissionGroups.get(name), flags);
1719 }
1720 }
1721
1722 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001723 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 synchronized (mPackages) {
1725 final int N = mPermissionGroups.size();
1726 ArrayList<PermissionGroupInfo> out
1727 = new ArrayList<PermissionGroupInfo>(N);
1728 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1729 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1730 }
1731 return out;
1732 }
1733 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001734
Amith Yamasani483f3b02012-03-13 16:08:00 -07001735 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
1736 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001737 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001739 if (ps != null) {
1740 if (ps.pkg == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001741 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
Kenny Root447106f2011-03-23 11:00:15 -07001742 if (pInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 return pInfo.applicationInfo;
1744 }
1745 return null;
1746 }
Amith Yamasani13593602012-03-22 16:16:17 -07001747 return PackageParser.generateApplicationInfo(ps.pkg, flags, ps.getStopped(userId),
1748 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 }
1750 return null;
1751 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001752
Amith Yamasani483f3b02012-03-13 16:08:00 -07001753 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
1754 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001755 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001757 if (ps != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001758 PackageParser.Package pkg = new PackageParser.Package(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001759 if (ps.pkg == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 ps.pkg = new PackageParser.Package(packageName);
1761 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001762 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1763 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1764 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
Amith Yamasani0b285492011-04-14 17:35:23 -07001765 ps.pkg.applicationInfo.dataDir =
1766 getDataPathForPackage(ps.pkg.packageName, 0).getPath();
Kenny Root85387d72010-08-26 10:13:11 -07001767 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 }
Amith Yamasani13593602012-03-22 16:16:17 -07001769 // ps.pkg.mSetEnabled = ps.getEnabled(userId);
1770 // ps.pkg.mSetStopped = ps.getStopped(userId);
1771 return generatePackageInfo(ps.pkg, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 }
1773 return null;
1774 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001775
Amith Yamasani483f3b02012-03-13 16:08:00 -07001776 @Override
1777 public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001778 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07001779 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 synchronized (mPackages) {
1781 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001782 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 TAG, "getApplicationInfo " + packageName
1784 + ": " + p);
1785 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001786 PackageSetting ps = mSettings.mPackages.get(packageName);
1787 if (ps == null) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 // Note: isEnabledLP() does not apply here - always return info
Amith Yamasani13593602012-03-22 16:16:17 -07001789 return PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
1790 ps.getEnabled(userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 }
1792 if ("android".equals(packageName)||"system".equals(packageName)) {
1793 return mAndroidApplication;
1794 }
1795 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001796 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 }
1798 }
1799 return null;
1800 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001801
1802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1804 mContext.enforceCallingOrSelfPermission(
1805 android.Manifest.permission.CLEAR_APP_CACHE, null);
1806 // Queue up an async operation since clearing cache may take a little while.
1807 mHandler.post(new Runnable() {
1808 public void run() {
1809 mHandler.removeCallbacks(this);
1810 int retCode = -1;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001811 retCode = mInstaller.freeCache(freeStorageSize);
1812 if (retCode < 0) {
1813 Slog.w(TAG, "Couldn't clear application caches");
1814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 if (observer != null) {
1816 try {
1817 observer.onRemoveCompleted(null, (retCode >= 0));
1818 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001819 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 }
1821 }
1822 }
1823 });
1824 }
1825
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001826 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001827 mContext.enforceCallingOrSelfPermission(
1828 android.Manifest.permission.CLEAR_APP_CACHE, null);
1829 // Queue up an async operation since clearing cache may take a little while.
1830 mHandler.post(new Runnable() {
1831 public void run() {
1832 mHandler.removeCallbacks(this);
1833 int retCode = -1;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001834 retCode = mInstaller.freeCache(freeStorageSize);
1835 if (retCode < 0) {
1836 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001837 }
1838 if(pi != null) {
1839 try {
1840 // Callback via pending intent
1841 int code = (retCode >= 0) ? 1 : 0;
1842 pi.sendIntent(null, code, null,
1843 null, null);
1844 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001845 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001846 }
1847 }
1848 }
1849 });
1850 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001851
Amith Yamasani483f3b02012-03-13 16:08:00 -07001852 @Override
1853 public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001854 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 synchronized (mPackages) {
1856 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001857
Kenny Root9718cf52011-02-23 16:45:26 -08001858 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001859 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001860 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1861 if (ps == null) return null;
1862 return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
1863 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 }
1865 if (mResolveComponentName.equals(component)) {
1866 return mResolveActivity;
1867 }
1868 }
1869 return null;
1870 }
1871
Amith Yamasani483f3b02012-03-13 16:08:00 -07001872 @Override
1873 public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001874 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 synchronized (mPackages) {
1876 PackageParser.Activity a = mReceivers.mActivities.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001877 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 TAG, "getReceiverInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001879 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001880 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1881 if (ps == null) return null;
1882 return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
1883 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 }
1885 }
1886 return null;
1887 }
1888
Amith Yamasani483f3b02012-03-13 16:08:00 -07001889 @Override
1890 public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001891 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 synchronized (mPackages) {
1893 PackageParser.Service s = mServices.mServices.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001894 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 TAG, "getServiceInfo " + component + ": " + s);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001896 if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001897 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1898 if (ps == null) return null;
1899 return PackageParser.generateServiceInfo(s, flags, ps.getStopped(userId),
1900 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 }
1902 }
1903 return null;
1904 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001905
Amith Yamasani483f3b02012-03-13 16:08:00 -07001906 @Override
1907 public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001908 if (!sUserManager.exists(userId)) return null;
Dianne Hackborn361199b2010-08-30 17:42:07 -07001909 synchronized (mPackages) {
1910 PackageParser.Provider p = mProvidersByComponent.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001911 if (DEBUG_PACKAGE_INFO) Log.v(
Dianne Hackborn361199b2010-08-30 17:42:07 -07001912 TAG, "getProviderInfo " + component + ": " + p);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001913 if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001914 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1915 if (ps == null) return null;
1916 return PackageParser.generateProviderInfo(p, flags, ps.getStopped(userId),
1917 ps.getEnabled(userId), userId);
Dianne Hackborn361199b2010-08-30 17:42:07 -07001918 }
1919 }
1920 return null;
1921 }
1922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 public String[] getSystemSharedLibraryNames() {
1924 Set<String> libSet;
1925 synchronized (mPackages) {
1926 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001927 int size = libSet.size();
1928 if (size > 0) {
1929 String[] libs = new String[size];
1930 libSet.toArray(libs);
1931 return libs;
1932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001934 return null;
1935 }
1936
1937 public FeatureInfo[] getSystemAvailableFeatures() {
1938 Collection<FeatureInfo> featSet;
1939 synchronized (mPackages) {
1940 featSet = mAvailableFeatures.values();
1941 int size = featSet.size();
1942 if (size > 0) {
1943 FeatureInfo[] features = new FeatureInfo[size+1];
1944 featSet.toArray(features);
1945 FeatureInfo fi = new FeatureInfo();
1946 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1947 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1948 features[size] = fi;
1949 return features;
1950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 }
1952 return null;
1953 }
1954
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001955 public boolean hasSystemFeature(String name) {
1956 synchronized (mPackages) {
1957 return mAvailableFeatures.containsKey(name);
1958 }
1959 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001960
Amith Yamasani483f3b02012-03-13 16:08:00 -07001961 private void checkValidCaller(int uid, int userId) {
1962 if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
1963 return;
1964
1965 throw new SecurityException("Caller uid=" + uid
1966 + " is not privileged to communicate with user=" + userId);
1967 }
1968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 public int checkPermission(String permName, String pkgName) {
1970 synchronized (mPackages) {
1971 PackageParser.Package p = mPackages.get(pkgName);
1972 if (p != null && p.mExtras != null) {
1973 PackageSetting ps = (PackageSetting)p.mExtras;
1974 if (ps.sharedUser != null) {
1975 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1976 return PackageManager.PERMISSION_GRANTED;
1977 }
1978 } else if (ps.grantedPermissions.contains(permName)) {
1979 return PackageManager.PERMISSION_GRANTED;
1980 }
1981 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07001982 if (!isPermissionEnforcedLocked(permName)) {
1983 return PackageManager.PERMISSION_GRANTED;
1984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986 return PackageManager.PERMISSION_DENIED;
1987 }
1988
1989 public int checkUidPermission(String permName, int uid) {
1990 synchronized (mPackages) {
Amith Yamasani742a6712011-05-04 14:49:28 -07001991 Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001993 GrantedPermissions gp = (GrantedPermissions)obj;
1994 if (gp.grantedPermissions.contains(permName)) {
1995 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001996 }
1997 } else {
1998 HashSet<String> perms = mSystemPermissions.get(uid);
1999 if (perms != null && perms.contains(permName)) {
2000 return PackageManager.PERMISSION_GRANTED;
2001 }
2002 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07002003 if (!isPermissionEnforcedLocked(permName)) {
2004 return PackageManager.PERMISSION_GRANTED;
2005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
2007 return PackageManager.PERMISSION_DENIED;
2008 }
2009
2010 private BasePermission findPermissionTreeLP(String permName) {
2011 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
2012 if (permName.startsWith(bp.name) &&
2013 permName.length() > bp.name.length() &&
2014 permName.charAt(bp.name.length()) == '.') {
2015 return bp;
2016 }
2017 }
2018 return null;
2019 }
2020
2021 private BasePermission checkPermissionTreeLP(String permName) {
2022 if (permName != null) {
2023 BasePermission bp = findPermissionTreeLP(permName);
2024 if (bp != null) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002025 if (bp.uid == UserId.getAppId(Binder.getCallingUid())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 return bp;
2027 }
2028 throw new SecurityException("Calling uid "
2029 + Binder.getCallingUid()
2030 + " is not allowed to add to permission tree "
2031 + bp.name + " owned by uid " + bp.uid);
2032 }
2033 }
2034 throw new SecurityException("No permission tree found for " + permName);
2035 }
2036
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002037 static boolean compareStrings(CharSequence s1, CharSequence s2) {
2038 if (s1 == null) {
2039 return s2 == null;
2040 }
2041 if (s2 == null) {
2042 return false;
2043 }
2044 if (s1.getClass() != s2.getClass()) {
2045 return false;
2046 }
2047 return s1.equals(s2);
2048 }
2049
2050 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
2051 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07002052 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002053 if (pi1.protectionLevel != pi2.protectionLevel) return false;
2054 if (!compareStrings(pi1.name, pi2.name)) return false;
2055 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
2056 // We'll take care of setting this one.
2057 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
2058 // These are not currently stored in settings.
2059 //if (!compareStrings(pi1.group, pi2.group)) return false;
2060 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
2061 //if (pi1.labelRes != pi2.labelRes) return false;
2062 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
2063 return true;
2064 }
2065
2066 boolean addPermissionLocked(PermissionInfo info, boolean async) {
2067 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
2068 throw new SecurityException("Label must be specified in permission");
2069 }
2070 BasePermission tree = checkPermissionTreeLP(info.name);
2071 BasePermission bp = mSettings.mPermissions.get(info.name);
2072 boolean added = bp == null;
2073 boolean changed = true;
Dianne Hackborne639da72012-02-21 15:11:13 -08002074 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002075 if (added) {
2076 bp = new BasePermission(info.name, tree.sourcePackage,
2077 BasePermission.TYPE_DYNAMIC);
2078 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
2079 throw new SecurityException(
2080 "Not allowed to modify non-dynamic permission "
2081 + info.name);
2082 } else {
Dianne Hackborne639da72012-02-21 15:11:13 -08002083 if (bp.protectionLevel == fixedLevel
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002084 && bp.perm.owner.equals(tree.perm.owner)
2085 && bp.uid == tree.uid
2086 && comparePermissionInfos(bp.perm.info, info)) {
2087 changed = false;
2088 }
2089 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002090 bp.protectionLevel = fixedLevel;
2091 info = new PermissionInfo(info);
2092 info.protectionLevel = fixedLevel;
2093 bp.perm = new PackageParser.Permission(tree.perm.owner, info);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002094 bp.perm.info.packageName = tree.perm.info.packageName;
2095 bp.uid = tree.uid;
2096 if (added) {
2097 mSettings.mPermissions.put(info.name, bp);
2098 }
2099 if (changed) {
2100 if (!async) {
Kenny Root447106f2011-03-23 11:00:15 -07002101 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002102 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002103 scheduleWriteSettingsLocked();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002104 }
2105 }
2106 return added;
2107 }
2108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 public boolean addPermission(PermissionInfo info) {
2110 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002111 return addPermissionLocked(info, false);
2112 }
2113 }
2114
2115 public boolean addPermissionAsync(PermissionInfo info) {
2116 synchronized (mPackages) {
2117 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 }
2119 }
2120
2121 public void removePermission(String name) {
2122 synchronized (mPackages) {
2123 checkPermissionTreeLP(name);
2124 BasePermission bp = mSettings.mPermissions.get(name);
2125 if (bp != null) {
2126 if (bp.type != BasePermission.TYPE_DYNAMIC) {
2127 throw new SecurityException(
2128 "Not allowed to modify non-dynamic permission "
2129 + name);
2130 }
2131 mSettings.mPermissions.remove(name);
Kenny Root447106f2011-03-23 11:00:15 -07002132 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 }
2134 }
2135 }
2136
Dianne Hackborne639da72012-02-21 15:11:13 -08002137 public void grantPermission(String packageName, String permissionName) {
2138 mContext.enforceCallingOrSelfPermission(
2139 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2140 synchronized (mPackages) {
2141 final PackageParser.Package pkg = mPackages.get(packageName);
2142 if (pkg == null) {
2143 throw new IllegalArgumentException("Unknown package: " + packageName);
2144 }
2145 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2146 if (bp == null) {
2147 throw new IllegalArgumentException("Unknown permission: " + packageName);
2148 }
2149 if (!pkg.requestedPermissions.contains(permissionName)) {
2150 throw new SecurityException("Package " + packageName
2151 + " has not requested permission " + permissionName);
2152 }
2153 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2154 throw new SecurityException("Permission " + permissionName
2155 + " is not a development permission");
2156 }
2157 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2158 if (ps == null) {
2159 return;
2160 }
2161 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2162 if (gp.grantedPermissions.add(permissionName)) {
2163 if (ps.haveGids) {
2164 gp.gids = appendInts(gp.gids, bp.gids);
2165 }
2166 mSettings.writeLPr();
2167 }
2168 }
2169 }
2170
2171 public void revokePermission(String packageName, String permissionName) {
2172 synchronized (mPackages) {
2173 final PackageParser.Package pkg = mPackages.get(packageName);
2174 if (pkg == null) {
2175 throw new IllegalArgumentException("Unknown package: " + packageName);
2176 }
2177 if (pkg.applicationInfo.uid != Binder.getCallingUid()) {
2178 mContext.enforceCallingOrSelfPermission(
2179 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2180 }
2181 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2182 if (bp == null) {
2183 throw new IllegalArgumentException("Unknown permission: " + packageName);
2184 }
2185 if (!pkg.requestedPermissions.contains(permissionName)) {
2186 throw new SecurityException("Package " + packageName
2187 + " has not requested permission " + permissionName);
2188 }
2189 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2190 throw new SecurityException("Permission " + permissionName
2191 + " is not a development permission");
2192 }
2193 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2194 if (ps == null) {
2195 return;
2196 }
2197 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2198 if (gp.grantedPermissions.remove(permissionName)) {
2199 gp.grantedPermissions.remove(permissionName);
2200 if (ps.haveGids) {
2201 gp.gids = removeInts(gp.gids, bp.gids);
2202 }
2203 mSettings.writeLPr();
2204 }
2205 }
2206 }
2207
Dianne Hackborn854060af2009-07-09 18:14:31 -07002208 public boolean isProtectedBroadcast(String actionName) {
2209 synchronized (mPackages) {
2210 return mProtectedBroadcasts.contains(actionName);
2211 }
2212 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 public int checkSignatures(String pkg1, String pkg2) {
2215 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002216 final PackageParser.Package p1 = mPackages.get(pkg1);
2217 final PackageParser.Package p2 = mPackages.get(pkg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 if (p1 == null || p1.mExtras == null
2219 || p2 == null || p2.mExtras == null) {
2220 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2221 }
Kenny Root447106f2011-03-23 11:00:15 -07002222 return compareSignatures(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 }
2224 }
2225
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002226 public int checkUidSignatures(int uid1, int uid2) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002227 // Map to base uids.
2228 uid1 = UserId.getAppId(uid1);
2229 uid2 = UserId.getAppId(uid2);
Kenny Root447106f2011-03-23 11:00:15 -07002230 // reader
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002231 synchronized (mPackages) {
2232 Signature[] s1;
2233 Signature[] s2;
Kenny Root447106f2011-03-23 11:00:15 -07002234 Object obj = mSettings.getUserIdLPr(uid1);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002235 if (obj != null) {
2236 if (obj instanceof SharedUserSetting) {
2237 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
2238 } else if (obj instanceof PackageSetting) {
2239 s1 = ((PackageSetting)obj).signatures.mSignatures;
2240 } else {
2241 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2242 }
2243 } else {
2244 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2245 }
Kenny Root447106f2011-03-23 11:00:15 -07002246 obj = mSettings.getUserIdLPr(uid2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002247 if (obj != null) {
2248 if (obj instanceof SharedUserSetting) {
2249 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
2250 } else if (obj instanceof PackageSetting) {
2251 s2 = ((PackageSetting)obj).signatures.mSignatures;
2252 } else {
2253 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2254 }
2255 } else {
2256 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2257 }
Kenny Root447106f2011-03-23 11:00:15 -07002258 return compareSignatures(s1, s2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002259 }
2260 }
2261
Kenny Root447106f2011-03-23 11:00:15 -07002262 static int compareSignatures(Signature[] s1, Signature[] s2) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002263 if (s1 == null) {
2264 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 ? PackageManager.SIGNATURE_NEITHER_SIGNED
2266 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
2267 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002268 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
2270 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002271 HashSet<Signature> set1 = new HashSet<Signature>();
2272 for (Signature sig : s1) {
2273 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002275 HashSet<Signature> set2 = new HashSet<Signature>();
2276 for (Signature sig : s2) {
2277 set2.add(sig);
2278 }
2279 // Make sure s2 contains all signatures in s1.
2280 if (set1.equals(set2)) {
2281 return PackageManager.SIGNATURE_MATCH;
2282 }
2283 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 }
2285
2286 public String[] getPackagesForUid(int uid) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002287 uid = UserId.getAppId(uid);
Kenny Root447106f2011-03-23 11:00:15 -07002288 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002290 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002292 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 final int N = sus.packages.size();
Kenny Root447106f2011-03-23 11:00:15 -07002294 final String[] res = new String[N];
2295 final Iterator<PackageSetting> it = sus.packages.iterator();
2296 int i = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 while (it.hasNext()) {
2298 res[i++] = it.next().name;
2299 }
2300 return res;
2301 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002302 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 return new String[] { ps.name };
2304 }
2305 }
2306 return null;
2307 }
2308
2309 public String getNameForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07002310 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 synchronized (mPackages) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002312 Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002314 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 return sus.name + ":" + sus.userId;
2316 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002317 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 return ps.name;
2319 }
2320 }
2321 return null;
2322 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 public int getUidForSharedUser(String sharedUserName) {
2325 if(sharedUserName == null) {
2326 return -1;
2327 }
Kenny Root447106f2011-03-23 11:00:15 -07002328 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002330 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
Amith Yamasani742a6712011-05-04 14:49:28 -07002331 if (suid == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 return -1;
2333 }
2334 return suid.userId;
2335 }
2336 }
2337
Amith Yamasani483f3b02012-03-13 16:08:00 -07002338 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002340 int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002341 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07002342 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2343 return chooseBestActivity(intent, resolvedType, flags, query, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02002344 }
2345
Mihai Predaeae850c2009-05-13 10:13:48 +02002346 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002347 int flags, List<ResolveInfo> query, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 if (query != null) {
2349 final int N = query.size();
2350 if (N == 1) {
2351 return query.get(0);
2352 } else if (N > 1) {
2353 // If there is more than one activity with the same priority,
2354 // then let the user decide between them.
2355 ResolveInfo r0 = query.get(0);
2356 ResolveInfo r1 = query.get(1);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002357 if (DEBUG_INTENT_MATCHING) {
2358 Log.d(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
2359 + r1.activityInfo.name + "=" + r1.priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
2361 // If the first activity has a higher priority, or a different
2362 // default, then it is always desireable to pick it.
2363 if (r0.priority != r1.priority
2364 || r0.preferredOrder != r1.preferredOrder
2365 || r0.isDefault != r1.isDefault) {
2366 return query.get(0);
2367 }
2368 // If we have saved a preference for a preferred activity for
2369 // this Intent, use that.
2370 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002371 flags, query, r0.priority, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 if (ri != null) {
2373 return ri;
2374 }
2375 return mResolveInfo;
2376 }
2377 }
2378 return null;
2379 }
2380
2381 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002382 int flags, List<ResolveInfo> query, int priority, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002383 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002384 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 synchronized (mPackages) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002386 if (intent.getSelector() != null) {
2387 intent = intent.getSelector();
2388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
2390 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02002391 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002392 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 if (prefs != null && prefs.size() > 0) {
2394 // First figure out how good the original match set is.
2395 // We will only allow preferred activities that came
2396 // from the same match quality.
2397 int match = 0;
Kenny Root447106f2011-03-23 11:00:15 -07002398
2399 if (DEBUG_PREFERRED) {
2400 Log.v(TAG, "Figuring out best match...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 }
Kenny Root447106f2011-03-23 11:00:15 -07002402
2403 final int N = query.size();
2404 for (int j=0; j<N; j++) {
2405 final ResolveInfo ri = query.get(j);
2406 if (DEBUG_PREFERRED) {
2407 Log.v(TAG, "Match for " + ri.activityInfo + ": 0x"
2408 + Integer.toHexString(match));
2409 }
2410 if (ri.match > match) {
2411 match = ri.match;
2412 }
2413 }
2414
2415 if (DEBUG_PREFERRED) {
2416 Log.v(TAG, "Best match: 0x" + Integer.toHexString(match));
2417 }
2418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 match &= IntentFilter.MATCH_CATEGORY_MASK;
2420 final int M = prefs.size();
2421 for (int i=0; i<M; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002422 final PreferredActivity pa = prefs.get(i);
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002423 if (pa.mPref.mMatch != match) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002424 continue;
2425 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07002426 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002427 if (DEBUG_PREFERRED) {
2428 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002429 if (ai != null) {
2430 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2431 } else {
2432 Log.v(TAG, " null");
2433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002435 if (ai == null) {
2436 // This previously registered preferred activity
2437 // component is no longer known. Most likely an update
2438 // to the app was installed and in the new version this
2439 // component no longer exists. Clean it up by removing
2440 // it from the preferred activities list, and skip it.
2441 Slog.w(TAG, "Removing dangling preferred activity: "
2442 + pa.mPref.mComponent);
2443 mSettings.mPreferredActivities.removeFilter(pa);
2444 continue;
2445 }
2446 for (int j=0; j<N; j++) {
2447 final ResolveInfo ri = query.get(j);
2448 if (!ri.activityInfo.applicationInfo.packageName
2449 .equals(ai.applicationInfo.packageName)) {
2450 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002452 if (!ri.activityInfo.name.equals(ai.name)) {
2453 continue;
2454 }
2455
2456 // Okay we found a previously set preferred app.
2457 // If the result set is different from when this
2458 // was created, we need to clear it and re-ask the
2459 // user their preference.
2460 if (!pa.mPref.sameSet(query, priority)) {
2461 Slog.i(TAG, "Result set changed, dropping preferred activity for "
2462 + intent + " type " + resolvedType);
2463 mSettings.mPreferredActivities.removeFilter(pa);
2464 return null;
2465 }
2466
2467 // Yay!
2468 return ri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 }
2470 }
2471 }
2472 }
2473 return null;
2474 }
2475
Amith Yamasani483f3b02012-03-13 16:08:00 -07002476 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 public List<ResolveInfo> queryIntentActivities(Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002478 String resolvedType, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002479 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002480 ComponentName comp = intent.getComponent();
2481 if (comp == null) {
2482 if (intent.getSelector() != null) {
2483 intent = intent.getSelector();
2484 comp = intent.getComponent();
2485 }
2486 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002489 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002490 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 if (ai != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002492 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 ri.activityInfo = ai;
2494 list.add(ri);
2495 }
2496 return list;
2497 }
2498
Kenny Root447106f2011-03-23 11:00:15 -07002499 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002501 final String pkgName = intent.getPackage();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002502 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002503 return mActivities.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002504 }
Kenny Root447106f2011-03-23 11:00:15 -07002505 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002506 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002507 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002508 pkg.activities, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002509 }
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08002510 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 }
2512 }
2513
Amith Yamasani483f3b02012-03-13 16:08:00 -07002514 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2516 Intent[] specifics, String[] specificTypes, Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002517 String resolvedType, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002518 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 final String resultsAction = intent.getAction();
2520
Kenny Root447106f2011-03-23 11:00:15 -07002521 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
Amith Yamasani483f3b02012-03-13 16:08:00 -07002522 | PackageManager.GET_RESOLVED_FILTER, userId);
Kenny Root447106f2011-03-23 11:00:15 -07002523
2524 if (DEBUG_INTENT_MATCHING) {
2525 Log.v(TAG, "Query " + intent + ": " + results);
2526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527
2528 int specificsPos = 0;
2529 int N;
2530
2531 // todo: note that the algorithm used here is O(N^2). This
2532 // isn't a problem in our current environment, but if we start running
2533 // into situations where we have more than 5 or 10 matches then this
2534 // should probably be changed to something smarter...
2535
2536 // First we go through and resolve each of the specific items
2537 // that were supplied, taking care of removing any corresponding
2538 // duplicate items in the generic resolve list.
2539 if (specifics != null) {
2540 for (int i=0; i<specifics.length; i++) {
2541 final Intent sintent = specifics[i];
2542 if (sintent == null) {
2543 continue;
2544 }
2545
Kenny Root447106f2011-03-23 11:00:15 -07002546 if (DEBUG_INTENT_MATCHING) {
2547 Log.v(TAG, "Specific #" + i + ": " + sintent);
2548 }
2549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 String action = sintent.getAction();
2551 if (resultsAction != null && resultsAction.equals(action)) {
2552 // If this action was explicitly requested, then don't
2553 // remove things that have it.
2554 action = null;
2555 }
Kenny Root447106f2011-03-23 11:00:15 -07002556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 ResolveInfo ri = null;
2558 ActivityInfo ai = null;
Kenny Root447106f2011-03-23 11:00:15 -07002559
2560 ComponentName comp = sintent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 if (comp == null) {
2562 ri = resolveIntent(
2563 sintent,
2564 specificTypes != null ? specificTypes[i] : null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002565 flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 if (ri == null) {
2567 continue;
2568 }
2569 if (ri == mResolveInfo) {
2570 // ACK! Must do something better with this.
2571 }
2572 ai = ri.activityInfo;
2573 comp = new ComponentName(ai.applicationInfo.packageName,
2574 ai.name);
2575 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002576 ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 if (ai == null) {
2578 continue;
2579 }
2580 }
2581
2582 // Look for any generic query activities that are duplicates
2583 // of this specific one, and remove them from the results.
Kenny Root9718cf52011-02-23 16:45:26 -08002584 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 N = results.size();
2586 int j;
2587 for (j=specificsPos; j<N; j++) {
2588 ResolveInfo sri = results.get(j);
2589 if ((sri.activityInfo.name.equals(comp.getClassName())
2590 && sri.activityInfo.applicationInfo.packageName.equals(
2591 comp.getPackageName()))
2592 || (action != null && sri.filter.matchAction(action))) {
2593 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002594 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 TAG, "Removing duplicate item from " + j
2596 + " due to specific " + specificsPos);
2597 if (ri == null) {
2598 ri = sri;
2599 }
2600 j--;
2601 N--;
2602 }
2603 }
2604
2605 // Add this specific item to its proper place.
2606 if (ri == null) {
2607 ri = new ResolveInfo();
2608 ri.activityInfo = ai;
2609 }
2610 results.add(specificsPos, ri);
2611 ri.specificIndex = i;
2612 specificsPos++;
2613 }
2614 }
2615
2616 // Now we go through the remaining generic results and remove any
2617 // duplicate actions that are found here.
2618 N = results.size();
2619 for (int i=specificsPos; i<N-1; i++) {
2620 final ResolveInfo rii = results.get(i);
2621 if (rii.filter == null) {
2622 continue;
2623 }
2624
2625 // Iterate over all of the actions of this result's intent
2626 // filter... typically this should be just one.
2627 final Iterator<String> it = rii.filter.actionsIterator();
2628 if (it == null) {
2629 continue;
2630 }
2631 while (it.hasNext()) {
2632 final String action = it.next();
2633 if (resultsAction != null && resultsAction.equals(action)) {
2634 // If this action was explicitly requested, then don't
2635 // remove things that have it.
2636 continue;
2637 }
2638 for (int j=i+1; j<N; j++) {
2639 final ResolveInfo rij = results.get(j);
2640 if (rij.filter != null && rij.filter.hasAction(action)) {
2641 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002642 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 TAG, "Removing duplicate item from " + j
2644 + " due to action " + action + " at " + i);
2645 j--;
2646 N--;
2647 }
2648 }
2649 }
2650
2651 // If the caller didn't request filter information, drop it now
2652 // so we don't have to marshall/unmarshall it.
2653 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2654 rii.filter = null;
2655 }
2656 }
2657
2658 // Filter out the caller activity if so requested.
2659 if (caller != null) {
2660 N = results.size();
2661 for (int i=0; i<N; i++) {
2662 ActivityInfo ainfo = results.get(i).activityInfo;
2663 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2664 && caller.getClassName().equals(ainfo.name)) {
2665 results.remove(i);
2666 break;
2667 }
2668 }
2669 }
2670
2671 // If the caller didn't request filter information,
2672 // drop them now so we don't have to
2673 // marshall/unmarshall it.
2674 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2675 N = results.size();
2676 for (int i=0; i<N; i++) {
2677 results.get(i).filter = null;
2678 }
2679 }
2680
Kenny Root9718cf52011-02-23 16:45:26 -08002681 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 return results;
2683 }
2684
Amith Yamasani483f3b02012-03-13 16:08:00 -07002685 @Override
2686 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
2687 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002688 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002689 ComponentName comp = intent.getComponent();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002690 if (comp == null) {
2691 if (intent.getSelector() != null) {
2692 intent = intent.getSelector();
2693 comp = intent.getComponent();
2694 }
2695 }
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002696 if (comp != null) {
2697 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002698 ActivityInfo ai = getReceiverInfo(comp, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002699 if (ai != null) {
2700 ResolveInfo ri = new ResolveInfo();
2701 ri.activityInfo = ai;
2702 list.add(ri);
2703 }
2704 return list;
2705 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002706
Kenny Root447106f2011-03-23 11:00:15 -07002707 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002709 String pkgName = intent.getPackage();
2710 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002711 return mReceivers.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002712 }
Kenny Root447106f2011-03-23 11:00:15 -07002713 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002714 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002715 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
2716 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002717 }
2718 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
2720 }
2721
Amith Yamasani483f3b02012-03-13 16:08:00 -07002722 @Override
2723 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
2724 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07002725 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 if (query != null) {
2727 if (query.size() >= 1) {
2728 // If there is more than one service with the same priority,
2729 // just arbitrarily pick the first one.
2730 return query.get(0);
2731 }
2732 }
2733 return null;
2734 }
2735
Amith Yamasani483f3b02012-03-13 16:08:00 -07002736 @Override
2737 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
2738 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002739 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002740 ComponentName comp = intent.getComponent();
2741 if (comp == null) {
2742 if (intent.getSelector() != null) {
2743 intent = intent.getSelector();
2744 comp = intent.getComponent();
2745 }
2746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002748 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002749 final ServiceInfo si = getServiceInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 if (si != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002751 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 ri.serviceInfo = si;
2753 list.add(ri);
2754 }
2755 return list;
2756 }
2757
Kenny Root447106f2011-03-23 11:00:15 -07002758 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002759 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002760 String pkgName = intent.getPackage();
2761 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002762 return mServices.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002763 }
Kenny Root447106f2011-03-23 11:00:15 -07002764 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002765 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002766 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
2767 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002768 }
2769 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 }
2771 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002772
Kenny Root0e2c0f32011-04-15 17:50:10 -07002773 private static final int getContinuationPoint(final String[] keys, final String key) {
2774 final int index;
2775 if (key == null) {
2776 index = 0;
2777 } else {
2778 final int insertPoint = Arrays.binarySearch(keys, key);
2779 if (insertPoint < 0) {
2780 index = -insertPoint;
2781 } else {
2782 index = insertPoint + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 }
2784 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002785 return index;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 }
2787
Kenny Root0e2c0f32011-04-15 17:50:10 -07002788 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) {
2789 final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
2790 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2791 final String[] keys;
Amith Yamasani483f3b02012-03-13 16:08:00 -07002792 int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793
Kenny Root447106f2011-03-23 11:00:15 -07002794 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 synchronized (mPackages) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002796 if (listUninstalled) {
2797 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
2798 } else {
2799 keys = mPackages.keySet().toArray(new String[mPackages.size()]);
2800 }
2801
2802 Arrays.sort(keys);
2803 int i = getContinuationPoint(keys, lastRead);
2804 final int N = keys.length;
2805
2806 while (i < N) {
2807 final String packageName = keys[i++];
2808
2809 PackageInfo pi = null;
2810 if (listUninstalled) {
2811 final PackageSetting ps = mSettings.mPackages.get(packageName);
2812 if (ps != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002813 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002815 } else {
2816 final PackageParser.Package p = mPackages.get(packageName);
2817 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07002818 pi = generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 }
2820 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002821
Henrik Engström9771a312012-02-21 09:05:17 +01002822 if (pi != null && list.append(pi)) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002823 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002824 }
2825 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002826
2827 if (i == N) {
2828 list.setLastSlice(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002831
2832 return list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 }
2834
Amith Yamasani483f3b02012-03-13 16:08:00 -07002835 @Override
Kenny Root0e2c0f32011-04-15 17:50:10 -07002836 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002837 String lastRead, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002838 if (!sUserManager.exists(userId)) return null;
Kenny Root0e2c0f32011-04-15 17:50:10 -07002839 final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
2840 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2841 final String[] keys;
2842
Kenny Root447106f2011-03-23 11:00:15 -07002843 // writer
Kenny Root0e2c0f32011-04-15 17:50:10 -07002844 synchronized (mPackages) {
2845 if (listUninstalled) {
2846 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
2847 } else {
2848 keys = mPackages.keySet().toArray(new String[mPackages.size()]);
2849 }
2850
2851 Arrays.sort(keys);
2852 int i = getContinuationPoint(keys, lastRead);
2853 final int N = keys.length;
2854
2855 while (i < N) {
2856 final String packageName = keys[i++];
2857
2858 ApplicationInfo ai = null;
Amith Yamasani13593602012-03-22 16:16:17 -07002859 final PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root0e2c0f32011-04-15 17:50:10 -07002860 if (listUninstalled) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002861 if (ps != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002862 ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
Kenny Root0e2c0f32011-04-15 17:50:10 -07002863 }
2864 } else {
2865 final PackageParser.Package p = mPackages.get(packageName);
Amith Yamasani13593602012-03-22 16:16:17 -07002866 if (p != null && ps != null) {
2867 ai = PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
2868 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 }
2870 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002871
Henrik Engström9771a312012-02-21 09:05:17 +01002872 if (ai != null && list.append(ai)) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002873 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 }
2875 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002876
2877 if (i == N) {
2878 list.setLastSlice(true);
2879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002880 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002881
2882 return list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
2884
2885 public List<ApplicationInfo> getPersistentApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002886 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887
Kenny Root447106f2011-03-23 11:00:15 -07002888 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002890 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
Amith Yamasani13593602012-03-22 16:16:17 -07002891 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002893 final PackageParser.Package p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 if (p.applicationInfo != null
2895 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07002896 && (!mSafeMode || isSystemApp(p))) {
Amith Yamasani13593602012-03-22 16:16:17 -07002897 PackageSetting ps = mSettings.mPackages.get(p.packageName);
2898 finalList.add(PackageParser.generateApplicationInfo(p, flags,
2899 ps != null ? ps.getStopped(userId) : false,
2900 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2901 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 }
2903 }
2904 }
2905
2906 return finalList;
2907 }
2908
Amith Yamasani483f3b02012-03-13 16:08:00 -07002909 @Override
2910 public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002911 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002912 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 synchronized (mPackages) {
2914 final PackageParser.Provider provider = mProviders.get(name);
Amith Yamasani13593602012-03-22 16:16:17 -07002915 PackageSetting ps = provider != null
2916 ? mSettings.mPackages.get(provider.owner.packageName)
2917 : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 return provider != null
Amith Yamasani483f3b02012-03-13 16:08:00 -07002919 && mSettings.isEnabledLPr(provider.info, flags, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 && (!mSafeMode || (provider.info.applicationInfo.flags
2921 &ApplicationInfo.FLAG_SYSTEM) != 0)
Amith Yamasani13593602012-03-22 16:16:17 -07002922 ? PackageParser.generateProviderInfo(provider, flags,
2923 ps != null ? ps.getStopped(userId) : false,
2924 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2925 userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 : null;
2927 }
2928 }
2929
Fred Quintana718d8a22009-04-29 17:53:20 -07002930 /**
2931 * @deprecated
2932 */
Kenny Root60f7ad82011-03-22 12:49:06 -07002933 @Deprecated
2934 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07002935 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002937 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
2938 .iterator();
Amith Yamasani13593602012-03-22 16:16:17 -07002939 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 while (i.hasNext()) {
2941 Map.Entry<String, PackageParser.Provider> entry = i.next();
2942 PackageParser.Provider p = entry.getValue();
Amith Yamasani13593602012-03-22 16:16:17 -07002943 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944
2945 if (p.syncable
2946 && (!mSafeMode || (p.info.applicationInfo.flags
2947 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2948 outNames.add(entry.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -07002949 outInfo.add(PackageParser.generateProviderInfo(p, 0,
2950 ps != null ? ps.getStopped(userId) : false,
2951 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2952 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
2954 }
2955 }
2956 }
2957
2958 public List<ProviderInfo> queryContentProviders(String processName,
2959 int uid, int flags) {
2960 ArrayList<ProviderInfo> finalList = null;
2961
Kenny Root447106f2011-03-23 11:00:15 -07002962 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002964 final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
Amith Yamasani483f3b02012-03-13 16:08:00 -07002965 final int userId = processName != null ?
2966 UserId.getUserId(uid) : UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002967 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002968 final PackageParser.Provider p = i.next();
Amith Yamasani13593602012-03-22 16:16:17 -07002969 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 if (p.info.authority != null
Kenny Root447106f2011-03-23 11:00:15 -07002971 && (processName == null
2972 || (p.info.processName.equals(processName)
Amith Yamasani483f3b02012-03-13 16:08:00 -07002973 && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
2974 && mSettings.isEnabledLPr(p.info, flags, userId)
Kenny Root447106f2011-03-23 11:00:15 -07002975 && (!mSafeMode
2976 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 if (finalList == null) {
2978 finalList = new ArrayList<ProviderInfo>(3);
2979 }
Amith Yamasani13593602012-03-22 16:16:17 -07002980 finalList.add(PackageParser.generateProviderInfo(p, flags,
2981 ps != null ? ps.getStopped(userId) : false,
2982 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2983 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 }
2985 }
2986 }
2987
2988 if (finalList != null) {
2989 Collections.sort(finalList, mProviderInitOrderSorter);
2990 }
2991
2992 return finalList;
2993 }
2994
2995 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2996 int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002997 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 synchronized (mPackages) {
2999 final PackageParser.Instrumentation i = mInstrumentation.get(name);
3000 return PackageParser.generateInstrumentationInfo(i, flags);
3001 }
3002 }
3003
3004 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
3005 int flags) {
3006 ArrayList<InstrumentationInfo> finalList =
3007 new ArrayList<InstrumentationInfo>();
3008
Kenny Root447106f2011-03-23 11:00:15 -07003009 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003010 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003011 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003013 final PackageParser.Instrumentation p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 if (targetPackage == null
3015 || targetPackage.equals(p.info.targetPackage)) {
3016 finalList.add(PackageParser.generateInstrumentationInfo(p,
3017 flags));
3018 }
3019 }
3020 }
3021
3022 return finalList;
3023 }
3024
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003025 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07003027 if (files == null) {
3028 Log.d(TAG, "No files in app dir " + dir);
3029 return;
3030 }
3031
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003032 if (DEBUG_PACKAGE_SCANNING) {
Joe Onorato431bb222010-10-18 19:13:23 -04003033 Log.d(TAG, "Scanning app dir " + dir);
3034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003035
3036 int i;
3037 for (i=0; i<files.length; i++) {
3038 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003039 if (!isPackageFilename(files[i])) {
3040 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003041 continue;
3042 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003043 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003044 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003045 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003046 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
3047 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003048 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003049 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003050 file.delete();
3051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 }
3053 }
3054
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003055 private static File getSettingsProblemFile() {
3056 File dataDir = Environment.getDataDirectory();
3057 File systemDir = new File(dataDir, "system");
3058 File fname = new File(systemDir, "uiderrors.txt");
3059 return fname;
3060 }
3061
Kenny Rootcf0b38c2011-03-22 14:17:59 -07003062 static void reportSettingsProblem(int priority, String msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003064 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 FileOutputStream out = new FileOutputStream(fname, true);
3066 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003067 SimpleDateFormat formatter = new SimpleDateFormat();
3068 String dateString = formatter.format(new Date(System.currentTimeMillis()));
3069 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 pw.close();
3071 FileUtils.setPermissions(
3072 fname.toString(),
3073 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
3074 -1, -1);
3075 } catch (java.io.IOException e) {
3076 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003077 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 }
3079
3080 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
3081 PackageParser.Package pkg, File srcFile, int parseFlags) {
3082 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07003083 if (ps != null
3084 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07003085 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07003086 if (ps.signatures.mSignatures != null
3087 && ps.signatures.mSignatures.length != 0) {
3088 // Optimization: reuse the existing cached certificates
3089 // if the package appears to be unchanged.
3090 pkg.mSignatures = ps.signatures.mSignatures;
3091 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 }
Jeff Browne7600722010-04-07 18:28:23 -07003093
3094 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003095 } else {
Jeff Browne7600722010-04-07 18:28:23 -07003096 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
3097 }
3098
3099 if (!pp.collectCertificates(pkg, parseFlags)) {
3100 mLastScanError = pp.getParseError();
3101 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 }
3103 }
3104 return true;
3105 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 /*
3108 * Scan a package and return the newly parsed package.
3109 * Returns null in case of errors and the error code is stored in mLastScanError
3110 */
3111 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003112 int parseFlags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003114 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003116 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07003118 pp.setOnlyCoreApps(mOnlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003120 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 if (pkg == null) {
3122 mLastScanError = pp.getParseError();
3123 return null;
3124 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003125 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 PackageSetting updatedPkg;
Kenny Root447106f2011-03-23 11:00:15 -07003127 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003129 // Look to see if we already know about this package.
3130 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003131 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003132 // This package has been renamed to its original name. Let's
3133 // use that.
Kenny Root447106f2011-03-23 11:00:15 -07003134 ps = mSettings.peekPackageLPr(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003135 }
3136 // If there was no original package, see one for the real package name.
3137 if (ps == null) {
Kenny Root447106f2011-03-23 11:00:15 -07003138 ps = mSettings.peekPackageLPr(pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003139 }
3140 // Check to see if this package could be hiding/updating a system
3141 // package. Must look for it either under the original or real
3142 // package name depending on our state.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003143 updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003145 // First check if this is a system package that may involve an update
3146 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07003147 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003148 // The path has changed from what was last scanned... check the
3149 // version of the new path against what we have stored to determine
3150 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003151 if (pkg.mVersionCode < ps.versionCode) {
3152 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003153 // Ignore entry. Skip it.
3154 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003155 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003156 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003157 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3158 return null;
3159 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003160 // The current app on the system partion is better than
3161 // what we have updated to on the data partition; switch
3162 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003163 // At this point, its safely assumed that package installation for
3164 // apps in system partition will go through. If not there won't be a working
3165 // version of the app
Kenny Root447106f2011-03-23 11:00:15 -07003166 // writer
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003167 synchronized (mPackages) {
3168 // Just remove the loaded entries from package lists.
3169 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003170 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003171 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003172 + "reverting from " + ps.codePathString
3173 + ": new version " + pkg.mVersionCode
3174 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003175
3176 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3177 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Kenny Root208d3412012-05-07 19:42:35 -07003178 synchronized (mInstaller) {
3179 args.cleanUpResourcesLI();
3180 }
3181 synchronized (mPackages) {
3182 mSettings.enableSystemPackageLPw(ps.name);
3183 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 }
3186 }
Kenny Root208d3412012-05-07 19:42:35 -07003187
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003188 if (updatedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07003189 // An updated system app will not have the PARSE_IS_SYSTEM flag set
3190 // initially
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003191 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
3192 }
3193 // Verify certificates against what was last scanned
3194 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003195 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003196 return null;
3197 }
Kenny Root208d3412012-05-07 19:42:35 -07003198
3199 /*
3200 * A new system app appeared, but we already had a non-system one of the
3201 * same name installed earlier.
3202 */
3203 boolean shouldHideSystemApp = false;
3204 if (updatedPkg == null && ps != null
3205 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
3206 /*
3207 * Check to make sure the signatures match first. If they don't,
3208 * wipe the installed application and its data.
3209 */
3210 if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
3211 != PackageManager.SIGNATURE_MATCH) {
3212 deletePackageLI(pkg.packageName, true, 0, null, false);
3213 ps = null;
3214 } else {
3215 /*
3216 * If the newly-added system app is an older version than the
3217 * already installed version, hide it. It will be scanned later
3218 * and re-added like an update.
3219 */
3220 if (pkg.mVersionCode < ps.versionCode) {
3221 shouldHideSystemApp = true;
3222 } else {
3223 /*
3224 * The newly found system app is a newer version that the
3225 * one previously installed. Simply remove the
3226 * already-installed application and replace it with our own
3227 * while keeping the application data.
3228 */
3229 Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
3230 + ps.codePathString + ": new version " + pkg.mVersionCode
3231 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003232 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3233 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Kenny Root208d3412012-05-07 19:42:35 -07003234 synchronized (mInstaller) {
3235 args.cleanUpResourcesLI();
3236 }
3237 }
3238 }
3239 }
3240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003241 // The apk is forward locked (not public) if its code and resources
3242 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003243 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003245 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07003246 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003247
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003248 String codePath = null;
3249 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003250 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
3251 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003252 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003253 } else {
3254 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003255 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003256 }
3257 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003258 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003259 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003260 codePath = pkg.mScanPath;
3261 // Set application objects path explicitly.
3262 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 // Note that we invoke the following method only if we are about to unpack an application
Kenny Root208d3412012-05-07 19:42:35 -07003264 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
3265 | SCAN_UPDATE_SIGNATURE, currentTime);
3266
3267 /*
3268 * If the system app should be overridden by a previously installed
3269 * data, hide the system app now and let the /data/app scan pick it up
3270 * again.
3271 */
3272 if (shouldHideSystemApp) {
3273 synchronized (mPackages) {
3274 /*
3275 * We have to grant systems permissions before we hide, because
3276 * grantPermissions will assume the package update is trying to
3277 * expand its permissions.
3278 */
3279 grantPermissionsLPw(pkg, true);
3280 mSettings.disableSystemPackageLPw(pkg.packageName);
3281 }
3282 }
3283
3284 return scannedPkg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 }
3286
Kenny Root85387d72010-08-26 10:13:11 -07003287 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
3288 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003289 pkg.mPath = pkg.mScanPath = destCodePath;
3290 pkg.applicationInfo.sourceDir = destCodePath;
3291 pkg.applicationInfo.publicSourceDir = destResPath;
3292 }
3293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 private static String fixProcessName(String defProcessName,
3295 String processName, int uid) {
3296 if (processName == null) {
3297 return defProcessName;
3298 }
3299 return processName;
3300 }
3301
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003302 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003303 PackageParser.Package pkg) {
3304 if (pkgSetting.signatures.mSignatures != null) {
3305 // Already existing package. Make sure signatures match
Kenny Root447106f2011-03-23 11:00:15 -07003306 if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003307 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003308 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003309 + " signatures do not match the previously installed version; ignoring!");
3310 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 return false;
3312 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003313 }
3314 // Check for shared user signatures
3315 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003316 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003317 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3318 Slog.e(TAG, "Package " + pkg.packageName
3319 + " has no signatures that match those in shared user "
3320 + pkgSetting.sharedUser.name + "; ignoring!");
3321 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
3322 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325 return true;
3326 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003327
Kenny Root461ff1f2011-08-09 09:43:03 -07003328 /**
3329 * Enforces that only the system UID or root's UID can call a method exposed
3330 * via Binder.
3331 *
3332 * @param message used as message if SecurityException is thrown
3333 * @throws SecurityException if the caller is not system or root
3334 */
3335 private static final void enforceSystemOrRoot(String message) {
3336 final int uid = Binder.getCallingUid();
3337 if (uid != Process.SYSTEM_UID && uid != 0) {
3338 throw new SecurityException(message);
3339 }
3340 }
3341
Dianne Hackborn661cd522011-08-22 00:26:20 -07003342 public void performBootDexOpt() {
3343 ArrayList<PackageParser.Package> pkgs = null;
3344 synchronized (mPackages) {
3345 if (mDeferredDexOpt.size() > 0) {
3346 pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt);
3347 mDeferredDexOpt.clear();
3348 }
3349 }
3350 if (pkgs != null) {
3351 for (int i=0; i<pkgs.size(); i++) {
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003352 if (!isFirstBoot()) {
3353 try {
3354 ActivityManagerNative.getDefault().showBootMessage(
3355 mContext.getResources().getString(
3356 com.android.internal.R.string.android_upgrading_apk,
3357 i+1, pkgs.size()), true);
3358 } catch (RemoteException e) {
3359 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003360 }
3361 PackageParser.Package p = pkgs.get(i);
3362 synchronized (mInstallLock) {
3363 if (!p.mDidDexOpt) {
3364 performDexOptLI(p, false, false);
3365 }
3366 }
3367 }
3368 }
3369 }
3370
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003371 public boolean performDexOpt(String packageName) {
Kenny Root461ff1f2011-08-09 09:43:03 -07003372 enforceSystemOrRoot("Only the system can request dexopt be performed");
3373
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003374 if (!mNoDexOpt) {
3375 return false;
3376 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003377
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003378 PackageParser.Package p;
3379 synchronized (mPackages) {
3380 p = mPackages.get(packageName);
3381 if (p == null || p.mDidDexOpt) {
3382 return false;
3383 }
3384 }
3385 synchronized (mInstallLock) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003386 return performDexOptLI(p, false, false) == DEX_OPT_PERFORMED;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003387 }
3388 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003389
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003390 static final int DEX_OPT_SKIPPED = 0;
3391 static final int DEX_OPT_PERFORMED = 1;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003392 static final int DEX_OPT_DEFERRED = 2;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003393 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003394
Dianne Hackborn661cd522011-08-22 00:26:20 -07003395 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003396 boolean performed = false;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003397 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003398 String path = pkg.mScanPath;
3399 int ret = 0;
3400 try {
3401 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003402 if (!forceDex && defer) {
3403 mDeferredDexOpt.add(pkg);
3404 return DEX_OPT_DEFERRED;
3405 } else {
3406 Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
3407 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
3408 !isForwardLocked(pkg));
3409 pkg.mDidDexOpt = true;
3410 performed = true;
3411 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003412 }
3413 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003414 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003415 ret = -1;
3416 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07003417 Slog.w(TAG, "IOException reading apk: " + path, e);
3418 ret = -1;
3419 } catch (dalvik.system.StaleDexCacheError e) {
3420 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
3421 ret = -1;
3422 } catch (Exception e) {
3423 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003424 ret = -1;
3425 }
3426 if (ret < 0) {
3427 //error from installer
3428 return DEX_OPT_FAILED;
3429 }
3430 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003431
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003432 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
3433 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08003434
Kenny Root447106f2011-03-23 11:00:15 -07003435 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003436 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003437 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003438 + " to " + newPkg.packageName
3439 + ": old package not in system partition");
3440 return false;
3441 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003442 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003443 + " to " + newPkg.packageName
3444 + ": old package still exists");
3445 return false;
3446 }
3447 return true;
3448 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003449
Amith Yamasani0b285492011-04-14 17:35:23 -07003450 File getDataPathForUser(int userId) {
3451 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003452 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003453
3454 private File getDataPathForPackage(String packageName, int userId) {
Kenny Root9c8625e2011-07-25 09:42:22 -07003455 /*
3456 * Until we fully support multiple users, return the directory we
3457 * previously would have. The PackageManagerTests will need to be
3458 * revised when this is changed back..
3459 */
3460 if (userId == 0) {
3461 return new File(mAppDataDir, packageName);
3462 } else {
3463 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003464 + File.separator + packageName);
Kenny Root9c8625e2011-07-25 09:42:22 -07003465 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003466 }
3467
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003468 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003469 int parseFlags, int scanMode, long currentTime) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003470 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08003471 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
3472 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003473 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003474 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003475 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
3476 return null;
3477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 mScanningPath = scanFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3481 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
3482 }
3483
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003484 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 synchronized (mPackages) {
3486 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003487 Slog.w(TAG, "*************************************************");
3488 Slog.w(TAG, "Core android package being redefined. Skipping.");
3489 Slog.w(TAG, " file=" + mScanningPath);
3490 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3492 return null;
3493 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 // Set up information for our fall-back user intent resolution
3496 // activity.
3497 mPlatformPackage = pkg;
3498 pkg.mVersionCode = mSdkVersion;
3499 mAndroidApplication = pkg.applicationInfo;
3500 mResolveActivity.applicationInfo = mAndroidApplication;
3501 mResolveActivity.name = ResolverActivity.class.getName();
3502 mResolveActivity.packageName = mAndroidApplication.packageName;
3503 mResolveActivity.processName = mAndroidApplication.processName;
3504 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3505 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08003506 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 mResolveActivity.exported = true;
3508 mResolveActivity.enabled = true;
3509 mResolveInfo.activityInfo = mResolveActivity;
3510 mResolveInfo.priority = 0;
3511 mResolveInfo.preferredOrder = 0;
3512 mResolveInfo.match = 0;
3513 mResolveComponentName = new ComponentName(
3514 mAndroidApplication.packageName, mResolveActivity.name);
3515 }
3516 }
3517
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003518 if (DEBUG_PACKAGE_SCANNING) {
3519 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3520 Log.d(TAG, "Scanning package " + pkg.packageName);
3521 }
3522
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003523 if (mPackages.containsKey(pkg.packageName)
3524 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003525 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3528 return null;
3529 }
3530
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003531 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003532 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
3533 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 SharedUserSetting suid = null;
3536 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003537
Kenny Root502e9a42011-01-10 13:48:15 -08003538 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003539 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08003540 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003541 pkg.mRealPackage = null;
3542 pkg.mAdoptPermissions = null;
3543 }
Kenny Root502e9a42011-01-10 13:48:15 -08003544
Kenny Root447106f2011-03-23 11:00:15 -07003545 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 synchronized (mPackages) {
3547 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07003548 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
3549 if (mTmpSharedLibraries == null ||
3550 mTmpSharedLibraries.length < mSharedLibraries.size()) {
3551 mTmpSharedLibraries = new String[mSharedLibraries.size()];
3552 }
3553 int num = 0;
3554 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
3555 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003556 final String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003558 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07003560 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
3562 return null;
3563 }
Dianne Hackborn49237342009-08-27 20:08:01 -07003564 mTmpSharedLibraries[num] = file;
3565 num++;
3566 }
3567 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
3568 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003569 final String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
Dianne Hackborn49237342009-08-27 20:08:01 -07003570 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003571 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07003572 + " desires unavailable shared library "
3573 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
3574 } else {
3575 mTmpSharedLibraries[num] = file;
3576 num++;
3577 }
3578 }
3579 if (num > 0) {
3580 pkg.usesLibraryFiles = new String[num];
3581 System.arraycopy(mTmpSharedLibraries, 0,
3582 pkg.usesLibraryFiles, 0, num);
3583 }
Kenny Root1683afa2011-01-07 14:27:50 -08003584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 if (pkg.mSharedUserId != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003587 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 pkg.applicationInfo.flags, true);
3589 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003590 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 + " for shared user failed");
3592 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3593 return null;
3594 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003595 if (DEBUG_PACKAGE_SCANNING) {
3596 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3597 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
3598 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 }
3600 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003601
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003602 // Check if we are renaming from an original package name.
3603 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003604 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08003605 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003606 // This package may need to be renamed to a previously
3607 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07003608 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003609 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003610 // This package had originally been installed as the
3611 // original name, and we have already taken care of
3612 // transitioning to the new one. Just update the new
3613 // one to continue using the old name.
3614 realName = pkg.mRealPackage;
3615 if (!pkg.packageName.equals(renamed)) {
3616 // Callers into this function may have already taken
3617 // care of renaming the package; only do it here if
3618 // it is not already done.
3619 pkg.setPackageName(renamed);
3620 }
3621
Dianne Hackbornc1552392010-03-03 16:19:01 -08003622 } else {
3623 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07003624 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08003625 pkg.mOriginalPackages.get(i))) != null) {
3626 // We do have the package already installed under its
3627 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07003628 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08003629 // New package is not compatible with original.
3630 origPackage = null;
3631 continue;
3632 } else if (origPackage.sharedUser != null) {
3633 // Make sure uid is compatible between packages.
3634 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003635 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08003636 + " to " + pkg.packageName + ": old uid "
3637 + origPackage.sharedUser.name
3638 + " differs from " + pkg.mSharedUserId);
3639 origPackage = null;
3640 continue;
3641 }
3642 } else {
3643 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
3644 + pkg.packageName + " to old name " + origPackage.name);
3645 }
3646 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003647 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003648 }
3649 }
3650 }
3651
3652 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003653 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003654 + " was transferred to another, but its .apk remains");
3655 }
3656
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003657 // Just create the setting, don't add it yet. For already existing packages
3658 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07003659 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003660 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3661 pkg.applicationInfo.flags, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003663 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3665 return null;
3666 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003667
3668 if (pkgSetting.origPackage != null) {
3669 // If we are first transitioning from an original package,
3670 // fix up the new package's name now. We need to do this after
3671 // looking up the package under its new name, so getPackageLP
3672 // can take care of fiddling things correctly.
3673 pkg.setPackageName(origPackage.name);
3674
3675 // File a report about this.
3676 String msg = "New package " + pkgSetting.realName
3677 + " renamed to replace old package " + pkgSetting.name;
3678 reportSettingsProblem(Log.WARN, msg);
3679
3680 // Make a note of it.
3681 mTransferedPackages.add(origPackage.name);
3682
3683 // No longer need to retain this.
3684 pkgSetting.origPackage = null;
3685 }
3686
3687 if (realName != null) {
3688 // Make a note of it.
3689 mTransferedPackages.add(pkg.packageName);
3690 }
3691
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003692 if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3694 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003695
Amith Yamasani13593602012-03-22 16:16:17 -07003696 pkg.applicationInfo.uid = pkgSetting.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003698
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003699 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003700 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 return null;
3702 }
3703 // The signature has changed, but this package is in the system
3704 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003705 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 // However... if this package is part of a shared user, but it
3707 // doesn't match the signature of the shared user, let's fail.
3708 // What this means is that you can't change the signatures
3709 // associated with an overall shared user, which doesn't seem all
3710 // that unreasonable.
3711 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003712 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003713 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3714 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3716 return null;
3717 }
3718 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003719 // File a report about this.
3720 String msg = "System package " + pkg.packageName
3721 + " signature changed; retaining data.";
3722 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003724
The Android Open Source Project10592532009-03-18 17:39:46 -07003725 // Verify that this new package doesn't have any content providers
3726 // that conflict with existing packages. Only do this if the
3727 // package isn't already installed, since we don't want to break
3728 // things that are installed.
3729 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08003730 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07003731 int i;
3732 for (i=0; i<N; i++) {
3733 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003734 if (p.info.authority != null) {
3735 String names[] = p.info.authority.split(";");
3736 for (int j = 0; j < names.length; j++) {
3737 if (mProviders.containsKey(names[j])) {
3738 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003739 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003740 " (in package " + pkg.applicationInfo.packageName +
3741 ") is already used by "
3742 + ((other != null && other.getComponentName() != null)
3743 ? other.getComponentName().getPackageName() : "?"));
3744 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3745 return null;
3746 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003747 }
3748 }
3749 }
3750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751
Kenny Root447106f2011-03-23 11:00:15 -07003752 if (pkg.mAdoptPermissions != null) {
3753 // This package wants to adopt ownership of permissions from
3754 // another package.
3755 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
3756 final String origName = pkg.mAdoptPermissions.get(i);
3757 final PackageSetting orig = mSettings.peekPackageLPr(origName);
3758 if (orig != null) {
3759 if (verifyPackageUpdateLPr(orig, pkg)) {
3760 Slog.i(TAG, "Adopting permissions from " + origName + " to "
3761 + pkg.packageName);
3762 mSettings.transferPermissionsLPw(origName, pkg.packageName);
3763 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003764 }
3765 }
3766 }
3767 }
Kenny Root447106f2011-03-23 11:00:15 -07003768
3769 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003770
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003771 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 pkg.applicationInfo.processName = fixProcessName(
3774 pkg.applicationInfo.packageName,
3775 pkg.applicationInfo.processName,
3776 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777
3778 File dataPath;
3779 if (mPlatformPackage == pkg) {
3780 // The system package is special.
3781 dataPath = new File (Environment.getDataDirectory(), "system");
3782 pkg.applicationInfo.dataDir = dataPath.getPath();
3783 } else {
3784 // This is a normal package, need to make its data directory.
Amith Yamasani0b285492011-04-14 17:35:23 -07003785 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003786
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003787 boolean uidError = false;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 if (dataPath.exists()) {
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003790 // XXX should really do this check for each user.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003791 mOutPermissions[1] = 0;
3792 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
Kenny Root85387d72010-08-26 10:13:11 -07003793
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003794 // If we have mismatched owners for the data path, we have a problem.
Jeff Brown10e89712011-07-08 18:52:57 -07003795 if (mOutPermissions[1] != pkg.applicationInfo.uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 boolean recovered = false;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003797 if (mOutPermissions[1] == 0) {
3798 // The directory somehow became owned by root. Wow.
3799 // This is probably because the system was stopped while
3800 // installd was in the middle of messing with its libs
3801 // directory. Ask installd to fix that.
3802 int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
3803 pkg.applicationInfo.uid);
3804 if (ret >= 0) {
3805 recovered = true;
3806 String msg = "Package " + pkg.packageName
3807 + " unexpectedly changed to uid 0; recovered to " +
3808 + pkg.applicationInfo.uid;
3809 reportSettingsProblem(Log.WARN, msg);
3810 }
3811 }
3812 if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
3813 || (scanMode&SCAN_BOOTING) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 // If this is a system app, we can at least delete its
3815 // current data so the application will still work.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003816 int ret = mInstaller.remove(pkgName, 0);
3817 if (ret >= 0) {
3818 // TODO: Kill the processes first
3819 // Remove the data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003820 sUserManager.removePackageForAllUsers(pkgName);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003821 // Old data gone!
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003822 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
3823 ? "System package " : "Third party package ";
3824 String msg = prefix + pkg.packageName
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003825 + " has changed from uid: "
3826 + mOutPermissions[1] + " to "
3827 + pkg.applicationInfo.uid + "; old data erased";
3828 reportSettingsProblem(Log.WARN, msg);
3829 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003830
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003831 // And now re-install the app.
3832 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3833 pkg.applicationInfo.uid);
3834 if (ret == -1) {
3835 // Ack should not happen!
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003836 msg = prefix + pkg.packageName
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003837 + " could not have data directory re-created after delete.";
3838 reportSettingsProblem(Log.WARN, msg);
3839 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3840 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003842 // Create data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003843 sUserManager.installPackageForAllUsers(pkgName,
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003844 pkg.applicationInfo.uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 if (!recovered) {
3847 mHasSystemUidErrors = true;
3848 }
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003849 } else if (!recovered) {
3850 // If we allow this install to proceed, we will be broken.
3851 // Abort, abort!
3852 mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED;
3853 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 }
3855 if (!recovered) {
3856 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3857 + pkg.applicationInfo.uid + "/fs_"
3858 + mOutPermissions[1];
Kenny Root85387d72010-08-26 10:13:11 -07003859 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 String msg = "Package " + pkg.packageName
3861 + " has mismatched uid: "
3862 + mOutPermissions[1] + " on disk, "
3863 + pkg.applicationInfo.uid + " in settings";
Kenny Root447106f2011-03-23 11:00:15 -07003864 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003866 mSettings.mReadMessages.append(msg);
3867 mSettings.mReadMessages.append('\n');
3868 uidError = true;
3869 if (!pkgSetting.uidError) {
3870 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 }
3873 }
3874 }
3875 pkg.applicationInfo.dataDir = dataPath.getPath();
3876 } else {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003877 if (DEBUG_PACKAGE_SCANNING) {
3878 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3879 Log.v(TAG, "Want this data dir: " + dataPath);
3880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003881 //invoke installer to do the actual installation
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003882 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3883 pkg.applicationInfo.uid);
3884 if (ret < 0) {
3885 // Error from installer
3886 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3887 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003889 // Create data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003890 sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 if (dataPath.exists()) {
3893 pkg.applicationInfo.dataDir = dataPath.getPath();
3894 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003895 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 pkg.applicationInfo.dataDir = null;
3897 }
3898 }
Kenny Root85387d72010-08-26 10:13:11 -07003899
3900 /*
3901 * Set the data dir to the default "/data/data/<package name>/lib"
3902 * if we got here without anyone telling us different (e.g., apps
3903 * stored on SD card have their native libraries stored in the ASEC
3904 * container with the APK).
Kenny Root806cc132010-09-12 08:34:19 -07003905 *
3906 * This happens during an upgrade from a package settings file that
3907 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07003908 */
Kenny Rootbd135c12010-10-05 12:26:27 -07003909 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
3910 if (pkgSetting.nativeLibraryPathString == null) {
3911 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
3912 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
3913 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
3914 } else {
3915 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
3916 }
Kenny Root85387d72010-08-26 10:13:11 -07003917 }
3918
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003919 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 }
3921
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003922 String path = scanFile.getPath();
3923 /* Note: We don't want to unpack the native binaries for
3924 * system applications, unless they have been updated
3925 * (the binaries are already under /system/lib).
3926 * Also, don't unpack libs for apps on the external card
3927 * since they should have their libraries in the ASEC
3928 * container already.
3929 *
3930 * In other words, we're going to unpack the binaries
3931 * only for non-system apps and system app upgrades.
3932 */
3933 if (pkg.applicationInfo.nativeLibraryDir != null) {
3934 try {
3935 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
Kenny Root5832ead2011-08-02 15:47:08 -07003936 final String dataPathString = dataPath.getCanonicalPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07003937
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003938 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
3939 /*
3940 * Upgrading from a previous version of the OS sometimes
3941 * leaves native libraries in the /data/data/<app>/lib
3942 * directory for system apps even when they shouldn't be.
3943 * Recent changes in the JNI library search path
3944 * necessitates we remove those to match previous behavior.
3945 */
3946 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
3947 Log.i(TAG, "removed obsolete native libraries for system package "
3948 + path);
Kenny Root831baa22010-10-05 12:29:25 -07003949 }
Kenny Root5832ead2011-08-02 15:47:08 -07003950 } else if (nativeLibraryDir.getParentFile().getCanonicalPath()
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003951 .equals(dataPathString)) {
3952 /*
Kenny Root66269ea2011-07-12 14:14:01 -07003953 * Make sure the native library dir isn't a symlink to
3954 * something. If it is, ask installd to remove it and create
3955 * a directory so we can copy to it afterwards.
3956 */
3957 boolean isSymLink;
3958 try {
3959 isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
3960 } catch (ErrnoException e) {
3961 // This shouldn't happen, but we'll fail-safe.
3962 isSymLink = true;
3963 }
3964 if (isSymLink) {
3965 mInstaller.unlinkNativeLibraryDirectory(dataPathString);
3966 }
3967
3968 /*
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003969 * If this is an internal application or our
3970 * nativeLibraryPath points to our data directory, unpack
Kenny Root66269ea2011-07-12 14:14:01 -07003971 * the libraries if necessary.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003972 */
Kenny Root66269ea2011-07-12 14:14:01 -07003973 NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003974 } else {
3975 Slog.i(TAG, "Linking native library dir for " + path);
3976 mInstaller.linkNativeLibraryDirectory(dataPathString,
3977 pkg.applicationInfo.nativeLibraryDir);
Kenny Root831baa22010-10-05 12:29:25 -07003978 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003979 } catch (IOException ioe) {
3980 Log.e(TAG, "Unable to get canonical file " + ioe.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003982 }
3983 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003984
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003985 if ((scanMode&SCAN_NO_DEX) == 0) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003986 if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0)
3987 == DEX_OPT_FAILED) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003988 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3989 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 }
3991 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 if (mFactoryTest && pkg.requestedPermissions.contains(
3994 android.Manifest.permission.FACTORY_TEST)) {
3995 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3996 }
3997
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003998 // Request the ActivityManager to kill the process(only for existing packages)
3999 // so that we do not end up in a confused state while the user is still using the older
4000 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004001 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004002 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004003 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004004 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004005
Kenny Root447106f2011-03-23 11:00:15 -07004006 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004008 // We don't expect installation to fail beyond this point,
4009 if ((scanMode&SCAN_MONITOR) != 0) {
4010 mAppDirs.put(pkg.mPath, pkg);
4011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07004013 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004015 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004016 // Make sure we don't accidentally delete its data.
4017 mSettings.mPackagesToBeCleaned.remove(pkgName);
4018
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004019 // Take care of first install / last update times.
4020 if (currentTime != 0) {
4021 if (pkgSetting.firstInstallTime == 0) {
4022 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
4023 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
4024 pkgSetting.lastUpdateTime = currentTime;
4025 }
4026 } else if (pkgSetting.firstInstallTime == 0) {
4027 // We need *something*. Take time time stamp of the file.
4028 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
4029 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
4030 if (scanFileTime != pkgSetting.timeStamp) {
4031 // A package on the system image has changed; consider this
4032 // to be an update.
4033 pkgSetting.lastUpdateTime = scanFileTime;
4034 }
4035 }
4036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 int N = pkg.providers.size();
4038 StringBuilder r = null;
4039 int i;
4040 for (i=0; i<N; i++) {
4041 PackageParser.Provider p = pkg.providers.get(i);
4042 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
4043 p.info.processName, pkg.applicationInfo.uid);
4044 mProvidersByComponent.put(new ComponentName(p.info.packageName,
4045 p.info.name), p);
4046 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004047 if (p.info.authority != null) {
4048 String names[] = p.info.authority.split(";");
4049 p.info.authority = null;
4050 for (int j = 0; j < names.length; j++) {
4051 if (j == 1 && p.syncable) {
4052 // We only want the first authority for a provider to possibly be
4053 // syncable, so if we already added this provider using a different
4054 // authority clear the syncable flag. We copy the provider before
4055 // changing it because the mProviders object contains a reference
4056 // to a provider that we don't want to change.
4057 // Only do this for the second authority since the resulting provider
4058 // object can be the same for all future authorities for this provider.
4059 p = new PackageParser.Provider(p);
4060 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004062 if (!mProviders.containsKey(names[j])) {
4063 mProviders.put(names[j], p);
4064 if (p.info.authority == null) {
4065 p.info.authority = names[j];
4066 } else {
4067 p.info.authority = p.info.authority + ";" + names[j];
4068 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004069 if (DEBUG_PACKAGE_SCANNING) {
4070 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4071 Log.d(TAG, "Registered content provider: " + names[j]
4072 + ", className = " + p.info.name + ", isSyncable = "
4073 + p.info.isSyncable);
4074 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004075 } else {
4076 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004077 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004078 " (in package " + pkg.applicationInfo.packageName +
4079 "): name already used by "
4080 + ((other != null && other.getComponentName() != null)
4081 ? other.getComponentName().getPackageName() : "?"));
4082 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 }
4084 }
4085 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4086 if (r == null) {
4087 r = new StringBuilder(256);
4088 } else {
4089 r.append(' ');
4090 }
4091 r.append(p.info.name);
4092 }
4093 }
4094 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004095 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 N = pkg.services.size();
4099 r = null;
4100 for (i=0; i<N; i++) {
4101 PackageParser.Service s = pkg.services.get(i);
4102 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
4103 s.info.processName, pkg.applicationInfo.uid);
4104 mServices.addService(s);
4105 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4106 if (r == null) {
4107 r = new StringBuilder(256);
4108 } else {
4109 r.append(' ');
4110 }
4111 r.append(s.info.name);
4112 }
4113 }
4114 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004115 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 N = pkg.receivers.size();
4119 r = null;
4120 for (i=0; i<N; i++) {
4121 PackageParser.Activity a = pkg.receivers.get(i);
4122 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4123 a.info.processName, pkg.applicationInfo.uid);
4124 mReceivers.addActivity(a, "receiver");
4125 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4126 if (r == null) {
4127 r = new StringBuilder(256);
4128 } else {
4129 r.append(' ');
4130 }
4131 r.append(a.info.name);
4132 }
4133 }
4134 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004135 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 N = pkg.activities.size();
4139 r = null;
4140 for (i=0; i<N; i++) {
4141 PackageParser.Activity a = pkg.activities.get(i);
4142 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4143 a.info.processName, pkg.applicationInfo.uid);
4144 mActivities.addActivity(a, "activity");
4145 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4146 if (r == null) {
4147 r = new StringBuilder(256);
4148 } else {
4149 r.append(' ');
4150 }
4151 r.append(a.info.name);
4152 }
4153 }
4154 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004155 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 N = pkg.permissionGroups.size();
4159 r = null;
4160 for (i=0; i<N; i++) {
4161 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
4162 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
4163 if (cur == null) {
4164 mPermissionGroups.put(pg.info.name, pg);
4165 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4166 if (r == null) {
4167 r = new StringBuilder(256);
4168 } else {
4169 r.append(' ');
4170 }
4171 r.append(pg.info.name);
4172 }
4173 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004174 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 + pg.info.packageName + " ignored: original from "
4176 + cur.info.packageName);
4177 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4178 if (r == null) {
4179 r = new StringBuilder(256);
4180 } else {
4181 r.append(' ');
4182 }
4183 r.append("DUP:");
4184 r.append(pg.info.name);
4185 }
4186 }
4187 }
4188 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004189 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 N = pkg.permissions.size();
4193 r = null;
4194 for (i=0; i<N; i++) {
4195 PackageParser.Permission p = pkg.permissions.get(i);
4196 HashMap<String, BasePermission> permissionMap =
4197 p.tree ? mSettings.mPermissionTrees
4198 : mSettings.mPermissions;
4199 p.group = mPermissionGroups.get(p.info.group);
4200 if (p.info.group == null || p.group != null) {
4201 BasePermission bp = permissionMap.get(p.info.name);
4202 if (bp == null) {
4203 bp = new BasePermission(p.info.name, p.info.packageName,
4204 BasePermission.TYPE_NORMAL);
4205 permissionMap.put(p.info.name, bp);
4206 }
4207 if (bp.perm == null) {
4208 if (bp.sourcePackage == null
4209 || bp.sourcePackage.equals(p.info.packageName)) {
4210 BasePermission tree = findPermissionTreeLP(p.info.name);
4211 if (tree == null
4212 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004213 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 bp.perm = p;
4215 bp.uid = pkg.applicationInfo.uid;
4216 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4217 if (r == null) {
4218 r = new StringBuilder(256);
4219 } else {
4220 r.append(' ');
4221 }
4222 r.append(p.info.name);
4223 }
4224 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004225 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 + p.info.packageName + " ignored: base tree "
4227 + tree.name + " is from package "
4228 + tree.sourcePackage);
4229 }
4230 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004231 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 + p.info.packageName + " ignored: original from "
4233 + bp.sourcePackage);
4234 }
4235 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4236 if (r == null) {
4237 r = new StringBuilder(256);
4238 } else {
4239 r.append(' ');
4240 }
4241 r.append("DUP:");
4242 r.append(p.info.name);
4243 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004244 if (bp.perm == p) {
4245 bp.protectionLevel = p.info.protectionLevel;
4246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004248 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 + p.info.packageName + " ignored: no group "
4250 + p.group);
4251 }
4252 }
4253 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004254 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 N = pkg.instrumentation.size();
4258 r = null;
4259 for (i=0; i<N; i++) {
4260 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
4261 a.info.packageName = pkg.applicationInfo.packageName;
4262 a.info.sourceDir = pkg.applicationInfo.sourceDir;
4263 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
4264 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07004265 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004266 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4268 if (r == null) {
4269 r = new StringBuilder(256);
4270 } else {
4271 r.append(' ');
4272 }
4273 r.append(a.info.name);
4274 }
4275 }
4276 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004277 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004279
Dianne Hackborn854060af2009-07-09 18:14:31 -07004280 if (pkg.protectedBroadcasts != null) {
4281 N = pkg.protectedBroadcasts.size();
4282 for (i=0; i<N; i++) {
4283 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
4284 }
4285 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 pkgSetting.setTimeStamp(scanFileTime);
4288 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 return pkg;
4291 }
4292
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004293 private void killApplication(String pkgName, int uid) {
4294 // Request the ActivityManager to kill the process(only for existing packages)
4295 // so that we do not end up in a confused state while the user is still using the older
4296 // version of the application while the new one gets installed.
4297 IActivityManager am = ActivityManagerNative.getDefault();
4298 if (am != null) {
4299 try {
4300 am.killApplicationWithUid(pkgName, uid);
4301 } catch (RemoteException e) {
4302 }
4303 }
4304 }
4305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004307 if (DEBUG_INSTALL) {
4308 if (chatty)
4309 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
4310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311
Kenny Root447106f2011-03-23 11:00:15 -07004312 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 mPackages.remove(pkg.applicationInfo.packageName);
4315 if (pkg.mPath != null) {
4316 mAppDirs.remove(pkg.mPath);
4317 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 int N = pkg.providers.size();
4320 StringBuilder r = null;
4321 int i;
4322 for (i=0; i<N; i++) {
4323 PackageParser.Provider p = pkg.providers.get(i);
4324 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
4325 p.info.name));
4326 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 /* The is another ContentProvider with this authority when
4329 * this app was installed so this authority is null,
4330 * Ignore it as we don't have to unregister the provider.
4331 */
4332 continue;
4333 }
4334 String names[] = p.info.authority.split(";");
4335 for (int j = 0; j < names.length; j++) {
4336 if (mProviders.get(names[j]) == p) {
4337 mProviders.remove(names[j]);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004338 if (DEBUG_REMOVE) {
4339 if (chatty)
4340 Log.d(TAG, "Unregistered content provider: " + names[j]
4341 + ", className = " + p.info.name + ", isSyncable = "
4342 + p.info.isSyncable);
4343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
4345 }
4346 if (chatty) {
4347 if (r == null) {
4348 r = new StringBuilder(256);
4349 } else {
4350 r.append(' ');
4351 }
4352 r.append(p.info.name);
4353 }
4354 }
4355 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004356 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + 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.services.size();
4360 r = null;
4361 for (i=0; i<N; i++) {
4362 PackageParser.Service s = pkg.services.get(i);
4363 mServices.removeService(s);
4364 if (chatty) {
4365 if (r == null) {
4366 r = new StringBuilder(256);
4367 } else {
4368 r.append(' ');
4369 }
4370 r.append(s.info.name);
4371 }
4372 }
4373 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004374 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 N = pkg.receivers.size();
4378 r = null;
4379 for (i=0; i<N; i++) {
4380 PackageParser.Activity a = pkg.receivers.get(i);
4381 mReceivers.removeActivity(a, "receiver");
4382 if (chatty) {
4383 if (r == null) {
4384 r = new StringBuilder(256);
4385 } else {
4386 r.append(' ');
4387 }
4388 r.append(a.info.name);
4389 }
4390 }
4391 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004392 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 N = pkg.activities.size();
4396 r = null;
4397 for (i=0; i<N; i++) {
4398 PackageParser.Activity a = pkg.activities.get(i);
4399 mActivities.removeActivity(a, "activity");
4400 if (chatty) {
4401 if (r == null) {
4402 r = new StringBuilder(256);
4403 } else {
4404 r.append(' ');
4405 }
4406 r.append(a.info.name);
4407 }
4408 }
4409 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004410 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + 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);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 BasePermission bp = mSettings.mPermissions.get(p.info.name);
4418 if (bp == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 bp = mSettings.mPermissionTrees.get(p.info.name);
4420 }
4421 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004422 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 if (chatty) {
4424 if (r == null) {
4425 r = new StringBuilder(256);
4426 } else {
4427 r.append(' ');
4428 }
4429 r.append(p.info.name);
4430 }
4431 }
4432 }
4433 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004434 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 N = pkg.instrumentation.size();
4438 r = null;
4439 for (i=0; i<N; i++) {
4440 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004441 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 if (chatty) {
4443 if (r == null) {
4444 r = new StringBuilder(256);
4445 } else {
4446 r.append(' ');
4447 }
4448 r.append(a.info.name);
4449 }
4450 }
4451 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004452 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 }
4454 }
4455 }
4456
4457 private static final boolean isPackageFilename(String name) {
4458 return name != null && name.endsWith(".apk");
4459 }
4460
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004461 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
4462 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
4463 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
4464 return true;
4465 }
4466 }
4467 return false;
4468 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004469
4470 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
4471 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
4472 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
4473
Kenny Root447106f2011-03-23 11:00:15 -07004474 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborne639da72012-02-21 15:11:13 -08004475 PackageParser.Package pkgInfo, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07004477 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004479 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004480 if (bp.packageSetting == null) {
4481 // We may not yet have parsed the package, so just see if
4482 // we still know about its settings.
4483 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4484 }
4485 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004486 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487 + " from package " + bp.sourcePackage);
4488 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004489 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4490 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4491 Slog.i(TAG, "Removing old permission tree: " + bp.name
4492 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004493 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004494 it.remove();
4495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 }
4497 }
4498
4499 // Make sure all dynamic permissions have been assigned to a package,
4500 // and make sure there are no dangling permissions.
4501 it = mSettings.mPermissions.values().iterator();
4502 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004503 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 if (bp.type == BasePermission.TYPE_DYNAMIC) {
4505 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
4506 + bp.name + " pkg=" + bp.sourcePackage
4507 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004508 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004509 final BasePermission tree = findPermissionTreeLP(bp.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07004510 if (tree != null && tree.perm != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004511 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 bp.perm = new PackageParser.Permission(tree.perm.owner,
4513 new PermissionInfo(bp.pendingInfo));
4514 bp.perm.info.packageName = tree.perm.info.packageName;
4515 bp.perm.info.name = bp.name;
4516 bp.uid = tree.uid;
4517 }
4518 }
4519 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004520 if (bp.packageSetting == null) {
4521 // We may not yet have parsed the package, so just see if
4522 // we still know about its settings.
4523 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4524 }
4525 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004526 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 + " from package " + bp.sourcePackage);
4528 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004529 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4530 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4531 Slog.i(TAG, "Removing old permission: " + bp.name
4532 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004533 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004534 it.remove();
4535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
4537 }
4538
4539 // Now update the permissions for all packages, in particular
4540 // replace the granted permissions of the system packages.
Dianne Hackborne639da72012-02-21 15:11:13 -08004541 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004542 for (PackageParser.Package pkg : mPackages.values()) {
4543 if (pkg != pkgInfo) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004544 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004545 }
4546 }
4547 }
4548
4549 if (pkgInfo != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004550 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 }
4552 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004553
Kenny Root447106f2011-03-23 11:00:15 -07004554 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
4555 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 if (ps == null) {
4557 return;
4558 }
4559 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08004560 HashSet<String> origPermissions = gp.grantedPermissions;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004561 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 if (replace) {
4564 ps.permissionsFixed = false;
4565 if (gp == ps) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004566 origPermissions = new HashSet<String>(gp.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 gp.grantedPermissions.clear();
4568 gp.gids = mGlobalGids;
4569 }
4570 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 if (gp.gids == null) {
4573 gp.gids = mGlobalGids;
4574 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 final int N = pkg.requestedPermissions.size();
4577 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07004578 final String name = pkg.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -08004579 //final boolean required = pkg.requestedPermssionsRequired.get(i);
Kenny Root447106f2011-03-23 11:00:15 -07004580 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004581 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004582 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004583 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 }
4585 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004586 if (bp != null && bp.packageSetting != null) {
4587 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004589 boolean allowedSig = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004590 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
4591 if (level == PermissionInfo.PROTECTION_NORMAL
4592 || level == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07004594 } else if (bp.packageSetting == null) {
4595 // This permission is invalid; skip it.
4596 allowed = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004597 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
Kenny Root447106f2011-03-23 11:00:15 -07004598 allowed = (compareSignatures(
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004599 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 == PackageManager.SIGNATURE_MATCH)
Kenny Root447106f2011-03-23 11:00:15 -07004601 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborne639da72012-02-21 15:11:13 -08004603 if (!allowed && (bp.protectionLevel
4604 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
Kenny Root85387d72010-08-26 10:13:11 -07004605 if (isSystemApp(pkg)) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004606 // For updated system applications, a system permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07004608 if (isUpdatedSystemApp(pkg)) {
Kenny Root447106f2011-03-23 11:00:15 -07004609 final PackageSetting sysPs = mSettings
4610 .getDisabledSystemPkgLPr(pkg.packageName);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004611 final GrantedPermissions origGp = sysPs.sharedUser != null
4612 ? sysPs.sharedUser : sysPs;
4613 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 allowed = true;
4615 } else {
4616 allowed = false;
4617 }
4618 } else {
4619 allowed = true;
4620 }
4621 }
4622 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004623 if (!allowed && (bp.protectionLevel
4624 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
4625 // For development permissions, a development permission
4626 // is granted only if it was already granted.
4627 if (origPermissions.contains(perm)) {
4628 allowed = true;
4629 } else {
4630 allowed = false;
4631 }
4632 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004633 if (allowed) {
4634 allowedSig = true;
4635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636 } else {
4637 allowed = false;
4638 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004639 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 if (gp != ps) {
4641 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
4642 }
4643 }
4644 if (allowed) {
4645 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
4646 && ps.permissionsFixed) {
4647 // If this is an existing, non-system package, then
4648 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07004649 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07004651 // Except... if this is a permission that was added
4652 // to the platform (note: need to only do this when
4653 // updating the platform).
4654 final int NP = PackageParser.NEW_PERMISSIONS.length;
4655 for (int ip=0; ip<NP; ip++) {
4656 final PackageParser.NewPermissionInfo npi
4657 = PackageParser.NEW_PERMISSIONS[ip];
4658 if (npi.name.equals(perm)
4659 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
4660 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07004661 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07004662 + pkg.packageName);
4663 break;
4664 }
4665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 }
4667 }
4668 if (allowed) {
4669 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004670 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 gp.grantedPermissions.add(perm);
4672 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004673 } else if (!ps.haveGids) {
4674 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 }
4676 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004677 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 + " to package " + pkg.packageName
4679 + " because it was previously installed without");
4680 }
4681 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004682 if (gp.grantedPermissions.remove(perm)) {
4683 changedPermission = true;
4684 gp.gids = removeInts(gp.gids, bp.gids);
4685 Slog.i(TAG, "Un-granting permission " + perm
4686 + " from package " + pkg.packageName
4687 + " (protectionLevel=" + bp.protectionLevel
4688 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4689 + ")");
4690 } else {
4691 Slog.w(TAG, "Not granting permission " + perm
4692 + " to package " + pkg.packageName
4693 + " (protectionLevel=" + bp.protectionLevel
4694 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4695 + ")");
4696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 }
4698 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004699 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 + " in package " + pkg.packageName);
4701 }
4702 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004703
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004704 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004705 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4706 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 // This is the first that we have heard about this package, so the
4708 // permissions we have now selected are fixed until explicitly
4709 // changed.
4710 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004712 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 private final class ActivityIntentResolver
4716 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004717 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004718 boolean defaultOnly, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004719 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004721 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 }
4723
Amith Yamasani483f3b02012-03-13 16:08:00 -07004724 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
4725 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004726 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004728 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004729 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 }
4731
Kenny Root60f7ad82011-03-22 12:49:06 -07004732 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004733 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004734 if (!sUserManager.exists(userId)) return null;
Mihai Predaeae850c2009-05-13 10:13:48 +02004735 if (packageActivities == null) {
4736 return null;
4737 }
4738 mFlags = flags;
4739 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004740 final int N = packageActivities.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07004741 ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
4742 new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004743
4744 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004745 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004746 intentFilters = packageActivities.get(i).intents;
4747 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07004748 PackageParser.ActivityIntentInfo[] array =
4749 new PackageParser.ActivityIntentInfo[intentFilters.size()];
4750 intentFilters.toArray(array);
4751 listCut.add(array);
Mihai Predac3320db2009-05-18 20:15:32 +02004752 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004753 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07004754 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02004755 }
4756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08004758 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004759 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08004760 if (DEBUG_SHOW_INFO)
4761 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 TAG, " " + type + " " +
4763 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004764 if (DEBUG_SHOW_INFO)
4765 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08004766 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004767 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08004769 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
4770 intent.setPriority(0);
4771 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
4772 + a.className + " with priority > 0, forcing to 0");
4773 }
Kenny Root9718cf52011-02-23 16:45:26 -08004774 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 Log.v(TAG, " IntentFilter:");
4776 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4777 }
4778 if (!intent.debugCheck()) {
4779 Log.w(TAG, "==> For Activity " + a.info.name);
4780 }
4781 addFilter(intent);
4782 }
4783 }
4784
4785 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004786 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004787 if (DEBUG_SHOW_INFO) {
4788 Log.v(TAG, " " + type + " "
4789 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
4790 : a.info.name) + ":");
4791 Log.v(TAG, " Class=" + a.info.name);
4792 }
4793 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004794 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004796 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 Log.v(TAG, " IntentFilter:");
4798 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4799 }
4800 removeFilter(intent);
4801 }
4802 }
4803
4804 @Override
4805 protected boolean allowFilterResult(
4806 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4807 ActivityInfo filterAi = filter.activity.info;
4808 for (int i=dest.size()-1; i>=0; i--) {
4809 ActivityInfo destAi = dest.get(i).activityInfo;
4810 if (destAi.name == filterAi.name
4811 && destAi.packageName == filterAi.packageName) {
4812 return false;
4813 }
4814 }
4815 return true;
4816 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07004819 protected ActivityIntentInfo[] newArray(int size) {
4820 return new ActivityIntentInfo[size];
4821 }
4822
4823 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07004824 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004825 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004826 PackageParser.Package p = filter.activity.owner;
4827 if (p != null) {
4828 PackageSetting ps = (PackageSetting)p.mExtras;
4829 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004830 // System apps are never considered stopped for purposes of
4831 // filtering, because there may be no way for the user to
4832 // actually re-launch them.
Amith Yamasani483f3b02012-03-13 16:08:00 -07004833 return ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004834 }
4835 }
4836 return false;
4837 }
4838
4839 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004840 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4841 return info.activity.owner.packageName;
4842 }
4843
4844 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004846 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004847 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004848 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 return null;
4850 }
4851 final PackageParser.Activity activity = info.activity;
4852 if (mSafeMode && (activity.info.applicationInfo.flags
4853 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4854 return null;
4855 }
4856 final ResolveInfo res = new ResolveInfo();
Amith Yamasani13593602012-03-22 16:16:17 -07004857 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
4858 res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
4859 ps != null ? ps.getStopped(userId) : false,
4860 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
4861 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4863 res.filter = info;
4864 }
4865 res.priority = info.getPriority();
4866 res.preferredOrder = activity.owner.mPreferredOrder;
4867 //System.out.println("Result: " + res.activityInfo.className +
4868 // " = " + res.priority);
4869 res.match = match;
4870 res.isDefault = info.hasDefault;
4871 res.labelRes = info.labelRes;
4872 res.nonLocalizedLabel = info.nonLocalizedLabel;
4873 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07004874 res.system = isSystemApp(res.activityInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004875 return res;
4876 }
4877
4878 @Override
4879 protected void sortResults(List<ResolveInfo> results) {
4880 Collections.sort(results, mResolvePrioritySorter);
4881 }
4882
4883 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004884 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004886 out.print(prefix); out.print(
4887 Integer.toHexString(System.identityHashCode(filter.activity)));
4888 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004889 out.print(filter.activity.getComponentShortName());
4890 out.print(" filter ");
4891 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 }
4893
4894// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4895// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4896// final List<ResolveInfo> retList = Lists.newArrayList();
4897// while (i.hasNext()) {
4898// final ResolveInfo resolveInfo = i.next();
4899// if (isEnabledLP(resolveInfo.activityInfo)) {
4900// retList.add(resolveInfo);
4901// }
4902// }
4903// return retList;
4904// }
4905
4906 // Keys are String (activity class name), values are Activity.
4907 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4908 = new HashMap<ComponentName, PackageParser.Activity>();
4909 private int mFlags;
4910 }
4911
4912 private final class ServiceIntentResolver
4913 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004914 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004915 boolean defaultOnly, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004917 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 }
4919
Amith Yamasani483f3b02012-03-13 16:08:00 -07004920 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
4921 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004922 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004924 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004925 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 }
4927
Kenny Root60f7ad82011-03-22 12:49:06 -07004928 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004929 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004930 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004931 if (packageServices == null) {
4932 return null;
4933 }
4934 mFlags = flags;
4935 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004936 final int N = packageServices.size();
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07004937 ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
4938 new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004939
4940 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4941 for (int i = 0; i < N; ++i) {
4942 intentFilters = packageServices.get(i).intents;
4943 if (intentFilters != null && intentFilters.size() > 0) {
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07004944 PackageParser.ServiceIntentInfo[] array =
4945 new PackageParser.ServiceIntentInfo[intentFilters.size()];
4946 intentFilters.toArray(array);
4947 listCut.add(array);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004948 }
4949 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07004950 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004951 }
4952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004954 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08004955 if (DEBUG_SHOW_INFO) {
4956 Log.v(TAG, " "
4957 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004959 Log.v(TAG, " Class=" + s.info.name);
4960 }
4961 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 int j;
4963 for (j=0; j<NI; j++) {
4964 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004965 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 Log.v(TAG, " IntentFilter:");
4967 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4968 }
4969 if (!intent.debugCheck()) {
4970 Log.w(TAG, "==> For Service " + s.info.name);
4971 }
4972 addFilter(intent);
4973 }
4974 }
4975
4976 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004977 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004978 if (DEBUG_SHOW_INFO) {
4979 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004981 Log.v(TAG, " Class=" + s.info.name);
4982 }
4983 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 int j;
4985 for (j=0; j<NI; j++) {
4986 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004987 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 Log.v(TAG, " IntentFilter:");
4989 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4990 }
4991 removeFilter(intent);
4992 }
4993 }
4994
4995 @Override
4996 protected boolean allowFilterResult(
4997 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4998 ServiceInfo filterSi = filter.service.info;
4999 for (int i=dest.size()-1; i>=0; i--) {
5000 ServiceInfo destAi = dest.get(i).serviceInfo;
5001 if (destAi.name == filterSi.name
5002 && destAi.packageName == filterSi.packageName) {
5003 return false;
5004 }
5005 }
5006 return true;
5007 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005009 @Override
Dianne Hackborn9ec6cdd2012-05-31 10:57:54 -07005010 protected PackageParser.ServiceIntentInfo[] newArray(int size) {
5011 return new PackageParser.ServiceIntentInfo[size];
5012 }
5013
5014 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07005015 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005016 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005017 PackageParser.Package p = filter.service.owner;
5018 if (p != null) {
5019 PackageSetting ps = (PackageSetting)p.mExtras;
5020 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07005021 // System apps are never considered stopped for purposes of
5022 // filtering, because there may be no way for the user to
5023 // actually re-launch them.
Amith Yamasani483f3b02012-03-13 16:08:00 -07005024 return ps.getStopped(userId)
5025 && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005026 }
5027 }
5028 return false;
5029 }
5030
5031 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005032 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
5033 return info.service.owner.packageName;
5034 }
5035
5036 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005038 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005039 if (!sUserManager.exists(userId)) return null;
Jason parksa3cdaa52011-01-13 14:15:43 -06005040 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005041 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 return null;
5043 }
5044 final PackageParser.Service service = info.service;
5045 if (mSafeMode && (service.info.applicationInfo.flags
5046 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5047 return null;
5048 }
5049 final ResolveInfo res = new ResolveInfo();
Amith Yamasani13593602012-03-22 16:16:17 -07005050 PackageSetting ps = (PackageSetting) service.owner.mExtras;
5051 res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
5052 ps != null ? ps.getStopped(userId) : false,
5053 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
5054 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
5056 res.filter = filter;
5057 }
5058 res.priority = info.getPriority();
5059 res.preferredOrder = service.owner.mPreferredOrder;
5060 //System.out.println("Result: " + res.activityInfo.className +
5061 // " = " + res.priority);
5062 res.match = match;
5063 res.isDefault = info.hasDefault;
5064 res.labelRes = info.labelRes;
5065 res.nonLocalizedLabel = info.nonLocalizedLabel;
5066 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005067 res.system = isSystemApp(res.serviceInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 return res;
5069 }
5070
5071 @Override
5072 protected void sortResults(List<ResolveInfo> results) {
5073 Collections.sort(results, mResolvePrioritySorter);
5074 }
5075
5076 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005077 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005078 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005079 out.print(prefix); out.print(
5080 Integer.toHexString(System.identityHashCode(filter.service)));
5081 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005082 out.print(filter.service.getComponentShortName());
5083 out.print(" filter ");
5084 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 }
5086
5087// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
5088// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
5089// final List<ResolveInfo> retList = Lists.newArrayList();
5090// while (i.hasNext()) {
5091// final ResolveInfo resolveInfo = (ResolveInfo) i;
5092// if (isEnabledLP(resolveInfo.serviceInfo)) {
5093// retList.add(resolveInfo);
5094// }
5095// }
5096// return retList;
5097// }
5098
5099 // Keys are String (activity class name), values are Activity.
5100 private final HashMap<ComponentName, PackageParser.Service> mServices
5101 = new HashMap<ComponentName, PackageParser.Service>();
5102 private int mFlags;
5103 };
5104
5105 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
5106 new Comparator<ResolveInfo>() {
5107 public int compare(ResolveInfo r1, ResolveInfo r2) {
5108 int v1 = r1.priority;
5109 int v2 = r2.priority;
5110 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
5111 if (v1 != v2) {
5112 return (v1 > v2) ? -1 : 1;
5113 }
5114 v1 = r1.preferredOrder;
5115 v2 = r2.preferredOrder;
5116 if (v1 != v2) {
5117 return (v1 > v2) ? -1 : 1;
5118 }
5119 if (r1.isDefault != r2.isDefault) {
5120 return r1.isDefault ? -1 : 1;
5121 }
5122 v1 = r1.match;
5123 v2 = r2.match;
5124 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005125 if (v1 != v2) {
5126 return (v1 > v2) ? -1 : 1;
5127 }
5128 if (r1.system != r2.system) {
5129 return r1.system ? -1 : 1;
5130 }
5131 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005132 }
5133 };
5134
5135 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
5136 new Comparator<ProviderInfo>() {
5137 public int compare(ProviderInfo p1, ProviderInfo p2) {
5138 final int v1 = p1.initOrder;
5139 final int v2 = p2.initOrder;
5140 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
5141 }
5142 };
5143
Kenny Root447106f2011-03-23 11:00:15 -07005144 static final void sendPackageBroadcast(String action, String pkg,
Amith Yamasani13593602012-03-22 16:16:17 -07005145 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 IActivityManager am = ActivityManagerNative.getDefault();
5147 if (am != null) {
5148 try {
Amith Yamasani13593602012-03-22 16:16:17 -07005149 int[] userIds = userId == UserId.USER_ALL
5150 ? sUserManager.getUserIds()
5151 : new int[] {userId};
5152 for (int id : userIds) {
5153 final Intent intent = new Intent(action,
5154 pkg != null ? Uri.fromParts("package", pkg, null) : null);
5155 if (extras != null) {
5156 intent.putExtras(extras);
5157 }
5158 if (targetPkg != null) {
5159 intent.setPackage(targetPkg);
5160 }
5161 // Modify the UID when posting to other users
5162 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
5163 if (uid > 0 && id > 0) {
5164 uid = UserId.getUid(id, UserId.getAppId(uid));
5165 intent.putExtra(Intent.EXTRA_UID, uid);
5166 }
5167 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5168 am.broadcastIntent(null, intent, null, finishedReceiver,
5169 0, null, null, null, finishedReceiver != null, false, id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 } catch (RemoteException ex) {
5172 }
5173 }
5174 }
Kenny Root300c13a2011-01-18 13:04:40 -08005175
5176 /**
5177 * Check if the external storage media is available. This is true if there
5178 * is a mounted external storage medium or if the external storage is
5179 * emulated.
5180 */
5181 private boolean isExternalMediaAvailable() {
5182 return mMediaMounted || Environment.isExternalStorageEmulated();
5183 }
5184
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005185 public String nextPackageToClean(String lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07005186 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005187 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005188 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005189 // If the external storage is no longer mounted at this point,
5190 // the caller may not have been able to delete all of this
5191 // packages files and can not delete any more. Bail.
5192 return null;
5193 }
5194 if (lastPackage != null) {
5195 mSettings.mPackagesToBeCleaned.remove(lastPackage);
5196 }
5197 return mSettings.mPackagesToBeCleaned.size() > 0
5198 ? mSettings.mPackagesToBeCleaned.get(0) : null;
5199 }
5200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005202 void schedulePackageCleaning(String packageName) {
5203 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
5204 }
5205
5206 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07005207 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005208 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005209 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005210 return;
5211 }
5212 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
5213 return;
5214 }
5215 }
5216 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
5217 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
5218 IActivityManager am = ActivityManagerNative.getDefault();
5219 if (am != null) {
5220 try {
5221 am.startService(null, intent, null);
5222 } catch (RemoteException e) {
5223 }
5224 }
5225 }
5226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 private final class AppDirObserver extends FileObserver {
5228 public AppDirObserver(String path, int mask, boolean isrom) {
5229 super(path, mask);
5230 mRootDir = path;
5231 mIsRom = isrom;
5232 }
5233
5234 public void onEvent(int event, String path) {
5235 String removedPackage = null;
5236 int removedUid = -1;
5237 String addedPackage = null;
5238 int addedUid = -1;
5239
Kenny Root447106f2011-03-23 11:00:15 -07005240 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 synchronized (mInstallLock) {
5242 String fullPathStr = null;
5243 File fullPath = null;
5244 if (path != null) {
5245 fullPath = new File(mRootDir, path);
5246 fullPathStr = fullPath.getPath();
5247 }
5248
Kenny Root9718cf52011-02-23 16:45:26 -08005249 if (DEBUG_APP_DIR_OBSERVER)
5250 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251
5252 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08005253 if (DEBUG_APP_DIR_OBSERVER)
5254 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 return;
5256 }
5257
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005258 // Ignore packages that are being installed or
5259 // have just been installed.
5260 if (ignoreCodePath(fullPathStr)) {
5261 return;
5262 }
5263 PackageParser.Package p = null;
Kenny Root447106f2011-03-23 11:00:15 -07005264 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005265 synchronized (mPackages) {
5266 p = mAppDirs.get(fullPathStr);
5267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005269 if (p != null) {
5270 removePackageLI(p, true);
5271 removedPackage = p.applicationInfo.packageName;
5272 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 }
5274 }
5275
5276 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005278 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07005279 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
5280 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 PackageParser.PARSE_CHATTY |
5282 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005283 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
5284 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005286 /*
5287 * TODO this seems dangerous as the package may have
5288 * changed since we last acquired the mPackages
5289 * lock.
5290 */
5291 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005293 updatePermissionsLPw(p.packageName, p,
Dianne Hackborne639da72012-02-21 15:11:13 -08005294 p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296 addedPackage = p.applicationInfo.packageName;
5297 addedUid = p.applicationInfo.uid;
5298 }
5299 }
5300 }
5301
Kenny Root447106f2011-03-23 11:00:15 -07005302 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005304 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
5306 }
5307
5308 if (removedPackage != null) {
5309 Bundle extras = new Bundle(1);
5310 extras.putInt(Intent.EXTRA_UID, removedUid);
5311 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005312 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07005313 extras, null, null, UserId.USER_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 }
5315 if (addedPackage != null) {
5316 Bundle extras = new Bundle(1);
5317 extras.putInt(Intent.EXTRA_UID, addedUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005318 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07005319 extras, null, null, UserId.USER_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 }
5321 }
5322
5323 private final String mRootDir;
5324 private final boolean mIsRom;
5325 }
Jacek Surazski65e13172009-04-28 15:26:38 +02005326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 /* Called when a downloaded package installation has been confirmed by the user */
5328 public void installPackage(
5329 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02005330 installPackage(packageURI, observer, flags, null);
5331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005332
Jacek Surazski65e13172009-04-28 15:26:38 +02005333 /* Called when a downloaded package installation has been confirmed by the user */
5334 public void installPackage(
5335 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
5336 final String installerPackageName) {
Kenny Root5ab21572011-07-27 11:11:19 -07005337 installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005338 null, null);
Kenny Root5ab21572011-07-27 11:11:19 -07005339 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005340
Kenny Root5ab21572011-07-27 11:11:19 -07005341 @Override
5342 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
5343 int flags, String installerPackageName, Uri verificationURI,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005344 ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
Kenny Root5ab21572011-07-27 11:11:19 -07005345 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
5346
5347 final int uid = Binder.getCallingUid();
5348
5349 final int filteredFlags;
5350
5351 if (uid == Process.SHELL_UID || uid == 0) {
5352 if (DEBUG_INSTALL) {
5353 Slog.v(TAG, "Install from ADB");
5354 }
5355 filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
5356 } else {
5357 filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
5358 }
5359
5360 final Message msg = mHandler.obtainMessage(INIT_COPY);
5361 msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005362 verificationURI, manifestDigest, encryptionParams);
Kenny Root5ab21572011-07-27 11:11:19 -07005363 mHandler.sendMessage(msg);
5364 }
5365
5366 @Override
Kenny Root05ca4c92011-09-15 10:36:25 -07005367 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
Kenny Root5ab21572011-07-27 11:11:19 -07005368 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
Kenny Root05ca4c92011-09-15 10:36:25 -07005369 final PackageVerificationResponse response = new PackageVerificationResponse(
5370 verificationCode, Binder.getCallingUid());
Kenny Root5ab21572011-07-27 11:11:19 -07005371 msg.arg1 = id;
Kenny Root05ca4c92011-09-15 10:36:25 -07005372 msg.obj = response;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005373 mHandler.sendMessage(msg);
5374 }
5375
Kenny Root05ca4c92011-09-15 10:36:25 -07005376 private ComponentName matchComponentForVerifier(String packageName,
5377 List<ResolveInfo> receivers) {
5378 ActivityInfo targetReceiver = null;
5379
5380 final int NR = receivers.size();
5381 for (int i = 0; i < NR; i++) {
5382 final ResolveInfo info = receivers.get(i);
5383 if (info.activityInfo == null) {
5384 continue;
5385 }
5386
5387 if (packageName.equals(info.activityInfo.packageName)) {
5388 targetReceiver = info.activityInfo;
5389 break;
5390 }
5391 }
5392
5393 if (targetReceiver == null) {
5394 return null;
5395 }
5396
5397 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
5398 }
5399
5400 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
5401 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
5402 if (pkgInfo.verifiers.length == 0) {
5403 return null;
5404 }
5405
5406 final int N = pkgInfo.verifiers.length;
5407 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
5408 for (int i = 0; i < N; i++) {
5409 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
5410
5411 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
5412 receivers);
5413 if (comp == null) {
5414 continue;
5415 }
5416
5417 final int verifierUid = getUidForVerifier(verifierInfo);
5418 if (verifierUid == -1) {
5419 continue;
5420 }
5421
5422 if (DEBUG_VERIFY) {
5423 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
5424 + " with the correct signature");
5425 }
5426 sufficientVerifiers.add(comp);
5427 verificationState.addSufficientVerifier(verifierUid);
5428 }
5429
5430 return sufficientVerifiers;
5431 }
5432
5433 private int getUidForVerifier(VerifierInfo verifierInfo) {
5434 synchronized (mPackages) {
5435 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
5436 if (pkg == null) {
5437 return -1;
5438 } else if (pkg.mSignatures.length != 1) {
5439 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5440 + " has more than one signature; ignoring");
5441 return -1;
5442 }
5443
5444 /*
5445 * If the public key of the package's signature does not match
5446 * our expected public key, then this is a different package and
5447 * we should skip.
5448 */
5449
5450 final byte[] expectedPublicKey;
5451 try {
5452 final Signature verifierSig = pkg.mSignatures[0];
5453 final PublicKey publicKey = verifierSig.getPublicKey();
5454 expectedPublicKey = publicKey.getEncoded();
5455 } catch (CertificateException e) {
5456 return -1;
5457 }
5458
5459 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
5460
5461 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
5462 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5463 + " does not have the expected public key; ignoring");
5464 return -1;
5465 }
5466
5467 return pkg.applicationInfo.uid;
5468 }
5469 }
5470
Christopher Tate1bb69062010-02-19 17:02:12 -08005471 public void finishPackageInstall(int token) {
Kenny Root461ff1f2011-08-09 09:43:03 -07005472 enforceSystemOrRoot("Only the system is allowed to finish installs");
5473
5474 if (DEBUG_INSTALL) {
5475 Slog.v(TAG, "BM finishing package install for " + token);
5476 }
5477
5478 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
Christopher Tate1bb69062010-02-19 17:02:12 -08005479 mHandler.sendMessage(msg);
5480 }
5481
Kenny Root5ab21572011-07-27 11:11:19 -07005482 /**
5483 * Get the verification agent timeout.
5484 *
5485 * @return verification timeout in milliseconds
5486 */
5487 private long getVerificationTimeout() {
5488 return android.provider.Settings.Secure.getLong(mContext.getContentResolver(),
5489 android.provider.Settings.Secure.PACKAGE_VERIFIER_TIMEOUT,
5490 DEFAULT_VERIFICATION_TIMEOUT);
5491 }
5492
5493 /**
rich canningsa6cfe522012-05-21 15:50:56 -07005494 * Get the default verification agent response code.
5495 *
5496 * @return default verification response code
5497 */
5498 private int getDefaultVerificationResponse() {
5499 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5500 android.provider.Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
5501 DEFAULT_VERIFICATION_RESPONSE);
5502 }
5503
5504 /**
Kenny Root5ab21572011-07-27 11:11:19 -07005505 * Check whether or not package verification has been enabled.
5506 *
5507 * @return true if verification should be performed
5508 */
5509 private boolean isVerificationEnabled() {
5510 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5511 android.provider.Settings.Secure.PACKAGE_VERIFIER_ENABLE,
5512 DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
5513 }
5514
Matt Finifterf8a98ed2012-05-14 15:43:34 -07005515 /**
5516 * Get the "allow unknown sources" setting.
5517 *
5518 * @return the current "allow unknown sources" setting
5519 */
5520 private int getUnknownSourcesSettings() {
5521 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5522 android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
5523 -1);
5524 }
5525
Kenny Rootf03b45f2011-02-23 17:25:45 -08005526 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08005527 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07005528 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08005529 synchronized (mPackages) {
5530 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
5531 if (targetPackageSetting == null) {
5532 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
5533 }
5534
5535 PackageSetting installerPackageSetting;
5536 if (installerPackageName != null) {
5537 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
5538 if (installerPackageSetting == null) {
5539 throw new IllegalArgumentException("Unknown installer package: "
5540 + installerPackageName);
5541 }
5542 } else {
5543 installerPackageSetting = null;
5544 }
5545
5546 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07005547 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08005548 if (obj != null) {
5549 if (obj instanceof SharedUserSetting) {
5550 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
5551 } else if (obj instanceof PackageSetting) {
5552 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
5553 } else {
5554 throw new SecurityException("Bad object " + obj + " for uid " + uid);
5555 }
5556 } else {
5557 throw new SecurityException("Unknown calling uid " + uid);
5558 }
5559
5560 // Verify: can't set installerPackageName to a package that is
5561 // not signed with the same cert as the caller.
5562 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005563 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08005564 installerPackageSetting.signatures.mSignatures)
5565 != PackageManager.SIGNATURE_MATCH) {
5566 throw new SecurityException(
5567 "Caller does not have same cert as new installer package "
5568 + installerPackageName);
5569 }
5570 }
5571
5572 // Verify: if target already has an installer package, it must
5573 // be signed with the same cert as the caller.
5574 if (targetPackageSetting.installerPackageName != null) {
5575 PackageSetting setting = mSettings.mPackages.get(
5576 targetPackageSetting.installerPackageName);
5577 // If the currently set package isn't valid, then it's always
5578 // okay to change it.
5579 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005580 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08005581 setting.signatures.mSignatures)
5582 != PackageManager.SIGNATURE_MATCH) {
5583 throw new SecurityException(
5584 "Caller does not have same cert as old installer package "
5585 + targetPackageSetting.installerPackageName);
5586 }
5587 }
5588 }
5589
5590 // Okay!
5591 targetPackageSetting.installerPackageName = installerPackageName;
5592 scheduleWriteSettingsLocked();
5593 }
5594 }
5595
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005596 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 // Queue up an async operation since the package installation may take a little while.
5598 mHandler.post(new Runnable() {
5599 public void run() {
5600 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005601 // Result object to be returned
5602 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005603 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005604 res.uid = -1;
5605 res.pkg = null;
5606 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005607 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005608 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005609 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005610 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005611 }
Kenny Root6dceb882012-04-12 14:23:49 -07005612 args.doPostInstall(res.returnCode, res.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005614
5615 // A restore should be performed at this point if (a) the install
5616 // succeeded, (b) the operation is not an update, and (c) the new
5617 // package has a backupAgent defined.
5618 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08005619 boolean doRestore = (!update
5620 && res.pkg != null
5621 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08005622
5623 // Set up the post-install work request bookkeeping. This will be used
5624 // and cleaned up by the post-install event handling regardless of whether
5625 // there's a restore pass performed. Token values are >= 1.
5626 int token;
5627 if (mNextInstallToken < 0) mNextInstallToken = 1;
5628 token = mNextInstallToken++;
5629
5630 PostInstallData data = new PostInstallData(args, res);
5631 mRunningInstalls.put(token, data);
5632 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
5633
5634 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
5635 // Pass responsibility to the Backup Manager. It will perform a
5636 // restore if appropriate, then pass responsibility back to the
5637 // Package Manager to run the post-install observer callbacks
5638 // and broadcasts.
5639 IBackupManager bm = IBackupManager.Stub.asInterface(
5640 ServiceManager.getService(Context.BACKUP_SERVICE));
5641 if (bm != null) {
5642 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
5643 + " to BM for possible restore");
5644 try {
5645 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
5646 } catch (RemoteException e) {
5647 // can't happen; the backup manager is local
5648 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005649 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08005650 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005651 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005652 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005653 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08005654 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005657
5658 if (!doRestore) {
5659 // No restore possible, or the Backup Manager was mysteriously not
5660 // available -- just fire the post-install work request directly.
5661 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
5662 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
5663 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 }
5666 });
5667 }
5668
Kenny Root5ab21572011-07-27 11:11:19 -07005669 private abstract class HandlerParams {
5670 private static final int MAX_RETRIES = 4;
5671
5672 /**
5673 * Number of times startCopy() has been attempted and had a non-fatal
5674 * error.
5675 */
5676 private int mRetries = 0;
5677
Dianne Hackborn7d608422011-08-07 16:24:18 -07005678 final boolean startCopy() {
5679 boolean res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005680 try {
Kenny Root5ab21572011-07-27 11:11:19 -07005681 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
5682
5683 if (++mRetries > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005684 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005685 mHandler.sendEmptyMessage(MCS_GIVE_UP);
5686 handleServiceError();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005687 return false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005688 } else {
5689 handleStartCopy();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005690 res = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005691 }
5692 } catch (RemoteException e) {
Kenny Root5ab21572011-07-27 11:11:19 -07005693 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005694 mHandler.sendEmptyMessage(MCS_RECONNECT);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005695 res = false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005696 }
5697 handleReturnCode();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005698 return res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005699 }
5700
5701 final void serviceError() {
Kenny Root5ab21572011-07-27 11:11:19 -07005702 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005703 handleServiceError();
5704 handleReturnCode();
5705 }
Kenny Root5ab21572011-07-27 11:11:19 -07005706
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005707 abstract void handleStartCopy() throws RemoteException;
5708 abstract void handleServiceError();
5709 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005710 }
5711
Kenny Root366949c2011-01-14 17:18:14 -08005712 class MeasureParams extends HandlerParams {
5713 private final PackageStats mStats;
5714 private boolean mSuccess;
5715
5716 private final IPackageStatsObserver mObserver;
5717
Kenny Roota69b7eb2012-05-14 14:47:06 -07005718 public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
Kenny Root366949c2011-01-14 17:18:14 -08005719 mObserver = observer;
5720 mStats = stats;
Kenny Root366949c2011-01-14 17:18:14 -08005721 }
5722
5723 @Override
5724 void handleStartCopy() throws RemoteException {
Kenny Roota69b7eb2012-05-14 14:47:06 -07005725 synchronized (mInstallLock) {
5726 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats);
5727 }
Kenny Root366949c2011-01-14 17:18:14 -08005728
Kenny Roota69b7eb2012-05-14 14:47:06 -07005729 final boolean mounted;
Kenny Root366949c2011-01-14 17:18:14 -08005730 if (Environment.isExternalStorageEmulated()) {
5731 mounted = true;
5732 } else {
5733 final String status = Environment.getExternalStorageState();
5734
5735 mounted = status.equals(Environment.MEDIA_MOUNTED)
5736 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
5737 }
5738
5739 if (mounted) {
5740 final File externalCacheDir = Environment
5741 .getExternalStorageAppCacheDirectory(mStats.packageName);
5742 final long externalCacheSize = mContainerService
5743 .calculateDirectorySize(externalCacheDir.getPath());
5744 mStats.externalCacheSize = externalCacheSize;
5745
5746 final File externalDataDir = Environment
5747 .getExternalStorageAppDataDirectory(mStats.packageName);
5748 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
5749 .getPath());
5750
5751 if (externalCacheDir.getParentFile().equals(externalDataDir)) {
5752 externalDataSize -= externalCacheSize;
5753 }
5754 mStats.externalDataSize = externalDataSize;
5755
5756 final File externalMediaDir = Environment
5757 .getExternalStorageAppMediaDirectory(mStats.packageName);
5758 mStats.externalMediaSize = mContainerService
Kenny Rootc7624d92011-02-23 16:25:25 -08005759 .calculateDirectorySize(externalMediaDir.getPath());
Kenny Rootbcd6c962011-01-17 11:21:49 -08005760
5761 final File externalObbDir = Environment
5762 .getExternalStorageAppObbDirectory(mStats.packageName);
5763 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
5764 .getPath());
Kenny Root366949c2011-01-14 17:18:14 -08005765 }
5766 }
5767
5768 @Override
5769 void handleReturnCode() {
5770 if (mObserver != null) {
5771 try {
5772 mObserver.onGetStatsCompleted(mStats, mSuccess);
5773 } catch (RemoteException e) {
5774 Slog.i(TAG, "Observer no longer exists.");
5775 }
5776 }
5777 }
5778
5779 @Override
5780 void handleServiceError() {
5781 Slog.e(TAG, "Could not measure application " + mStats.packageName
5782 + " external storage");
5783 }
5784 }
5785
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005786 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005787 final IPackageInstallObserver observer;
5788 int flags;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005789
5790 private final Uri mPackageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005791 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005792 final Uri verificationURI;
5793 final ManifestDigest manifestDigest;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005794 private InstallArgs mArgs;
5795 private int mRet;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005796 private File mTempPackage;
5797 final ContainerEncryptionParams encryptionParams;
Kenny Root5ab21572011-07-27 11:11:19 -07005798
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005799 InstallParams(Uri packageURI,
5800 IPackageInstallObserver observer, int flags,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005801 String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
5802 ContainerEncryptionParams encryptionParams) {
5803 this.mPackageURI = packageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005804 this.flags = flags;
5805 this.observer = observer;
5806 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005807 this.verificationURI = verificationURI;
5808 this.manifestDigest = manifestDigest;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005809 this.encryptionParams = encryptionParams;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005810 }
5811
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005812 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
5813 String packageName = pkgLite.packageName;
5814 int installLocation = pkgLite.installLocation;
5815 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07005816 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005817 synchronized (mPackages) {
5818 PackageParser.Package pkg = mPackages.get(packageName);
5819 if (pkg != null) {
5820 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5821 // Check for updated system application.
5822 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5823 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005824 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005825 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
5826 }
5827 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5828 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005829 if (onSd) {
5830 // Install flag overrides everything.
5831 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5832 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005833 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005834 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
5835 // Application explicitly specified internal.
5836 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5837 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
5838 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005839 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005840 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07005841 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005842 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5843 }
5844 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005845 }
5846 }
5847 } else {
5848 // Invalid install. Return error code
5849 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
5850 }
5851 }
5852 }
5853 // All the special cases have been taken care of.
5854 // Return result based on recommended install location.
5855 if (onSd) {
5856 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5857 }
5858 return pkgLite.recommendedInstallLocation;
5859 }
5860
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005861 /*
5862 * Invoke remote method to get package information and install
5863 * location values. Override install location based on default
5864 * policy if needed and then create install arguments based
5865 * on the install location.
5866 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005867 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08005868 int ret = PackageManager.INSTALL_SUCCEEDED;
Kenny Root05ca4c92011-09-15 10:36:25 -07005869 final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
5870 final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
5871 PackageInfoLite pkgLite = null;
5872
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005873 if (onInt && onSd) {
5874 // Check if both bits are set.
5875 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
5876 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005877 } else {
Kenny Root62e1b4e2011-03-14 17:13:39 -07005878 final long lowThreshold;
5879
5880 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
5881 .getService(DeviceStorageMonitorService.SERVICE);
5882 if (dsm == null) {
5883 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
5884 lowThreshold = 0L;
5885 } else {
5886 lowThreshold = dsm.getMemoryLowThreshold();
5887 }
5888
Kenny Root11128572010-10-11 10:51:32 -07005889 try {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005890 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
Kenny Root11128572010-10-11 10:51:32 -07005891 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root11128572010-10-11 10:51:32 -07005892
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005893 final File packageFile;
5894 if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
5895 ParcelFileDescriptor out = null;
5896
5897 mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
5898 if (mTempPackage != null) {
5899 try {
5900 out = ParcelFileDescriptor.open(mTempPackage,
5901 ParcelFileDescriptor.MODE_READ_WRITE);
5902 } catch (FileNotFoundException e) {
5903 Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
5904 }
5905
5906 // Make a temporary file for decryption.
5907 ret = mContainerService
5908 .copyResource(mPackageURI, encryptionParams, out);
5909
5910 packageFile = mTempPackage;
5911
5912 FileUtils.setPermissions(packageFile.getAbsolutePath(),
5913 FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IROTH,
5914 -1, -1);
5915 } else {
5916 packageFile = null;
5917 }
5918 } else {
5919 packageFile = new File(mPackageURI.getPath());
5920 }
5921
5922 if (packageFile != null) {
5923 // Remote call to find out default install location
5924 pkgLite = mContainerService.getMinimalPackageInfo(
5925 packageFile.getAbsolutePath(), flags, lowThreshold);
5926 }
5927 } finally {
5928 mContext.revokeUriPermission(mPackageURI,
5929 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5930 }
5931 }
5932
5933 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005934 int loc = pkgLite.recommendedInstallLocation;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005935 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005936 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005937 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005938 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005939 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005940 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5941 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
5942 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005943 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
5944 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005945 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
Kenny Root1ebd74a2011-08-03 15:09:44 -07005946 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005947 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005948 // Override with defaults if needed.
5949 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005950 if (!onSd && !onInt) {
5951 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005952 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
5953 // Set the flag to install on external media.
5954 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005955 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005956 } else {
5957 // Make sure the flag for installing on external
5958 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005959 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005960 flags &= ~PackageManager.INSTALL_EXTERNAL;
5961 }
5962 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005963 }
5964 }
Kenny Root5ab21572011-07-27 11:11:19 -07005965
5966 final InstallArgs args = createInstallArgs(this);
Kenny Root05ca4c92011-09-15 10:36:25 -07005967 mArgs = args;
5968
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005969 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Kenny Root5ab21572011-07-27 11:11:19 -07005970 /*
5971 * Determine if we have any installed package verifiers. If we
5972 * do, then we'll defer to them to verify the packages.
5973 */
Kenny Root05ca4c92011-09-15 10:36:25 -07005974 final int requiredUid = mRequiredVerifierPackage == null ? -1
Amith Yamasani483f3b02012-03-13 16:08:00 -07005975 : getPackageUid(mRequiredVerifierPackage, 0);
Kenny Root05ca4c92011-09-15 10:36:25 -07005976 if (requiredUid != -1 && isVerificationEnabled()) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005977 final Intent verification = new Intent(
5978 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
5979 verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
Kenny Root05ca4c92011-09-15 10:36:25 -07005980 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root5ab21572011-07-27 11:11:19 -07005981
Kenny Root05ca4c92011-09-15 10:36:25 -07005982 final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005983 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07005984
5985 if (DEBUG_VERIFY) {
Kenny Root5ab21572011-07-27 11:11:19 -07005986 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
Kenny Root05ca4c92011-09-15 10:36:25 -07005987 + verification.toString() + " with " + pkgLite.verifiers.length
5988 + " optional verifiers");
Kenny Root5ab21572011-07-27 11:11:19 -07005989 }
5990
5991 final int verificationId = mPendingVerificationToken++;
5992
5993 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
5994
5995 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
5996 installerPackageName);
5997
5998 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
5999
6000 if (verificationURI != null) {
6001 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
6002 verificationURI);
6003 }
6004
Kenny Root05ca4c92011-09-15 10:36:25 -07006005 final PackageVerificationState verificationState = new PackageVerificationState(
6006 requiredUid, args);
6007
6008 mPendingVerification.append(verificationId, verificationState);
6009
6010 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
6011 receivers, verificationState);
Kenny Root5ab21572011-07-27 11:11:19 -07006012
6013 /*
Kenny Root05ca4c92011-09-15 10:36:25 -07006014 * If any sufficient verifiers were listed in the package
6015 * manifest, attempt to ask them.
Kenny Root5ab21572011-07-27 11:11:19 -07006016 */
Kenny Root05ca4c92011-09-15 10:36:25 -07006017 if (sufficientVerifiers != null) {
6018 final int N = sufficientVerifiers.size();
6019 if (N == 0) {
6020 Slog.i(TAG, "Additional verifiers required, but none installed.");
6021 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
6022 } else {
6023 for (int i = 0; i < N; i++) {
6024 final ComponentName verifierComponent = sufficientVerifiers.get(i);
6025
6026 final Intent sufficientIntent = new Intent(verification);
6027 sufficientIntent.setComponent(verifierComponent);
6028
6029 mContext.sendBroadcast(sufficientIntent);
6030 }
6031 }
6032 }
6033
6034 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
6035 mRequiredVerifierPackage, receivers);
6036 if (ret == PackageManager.INSTALL_SUCCEEDED
6037 && mRequiredVerifierPackage != null) {
6038 /*
6039 * Send the intent to the required verification agent,
6040 * but only start the verification timeout after the
6041 * target BroadcastReceivers have run.
6042 */
6043 verification.setComponent(requiredVerifierComponent);
6044 mContext.sendOrderedBroadcast(verification,
6045 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6046 new BroadcastReceiver() {
6047 @Override
6048 public void onReceive(Context context, Intent intent) {
6049 final Message msg = mHandler
6050 .obtainMessage(CHECK_PENDING_VERIFICATION);
6051 msg.arg1 = verificationId;
6052 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
6053 }
6054 }, null, 0, null, null);
6055
6056 /*
6057 * We don't want the copy to proceed until verification
6058 * succeeds, so null out this field.
6059 */
6060 mArgs = null;
6061 }
Kenny Root5ab21572011-07-27 11:11:19 -07006062 } else {
Kenny Root05ca4c92011-09-15 10:36:25 -07006063 /*
6064 * No package verification is enabled, so immediately start
6065 * the remote call to initiate copy using temporary file.
6066 */
Kenny Root5ab21572011-07-27 11:11:19 -07006067 ret = args.copyApk(mContainerService, true);
6068 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006069 }
Kenny Root5ab21572011-07-27 11:11:19 -07006070
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006071 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006072 }
6073
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006074 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006075 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07006076 // If mArgs is null, then MCS couldn't be reached. When it
6077 // reconnects, it will try again to install. At that point, this
6078 // will succeed.
6079 if (mArgs != null) {
6080 processPendingInstall(mArgs, mRet);
6081 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006082
6083 if (mTempPackage != null) {
6084 if (!mTempPackage.delete()) {
6085 Slog.w(TAG, "Couldn't delete temporary file: "
6086 + mTempPackage.getAbsolutePath());
6087 }
6088 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006089 }
6090
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006091 @Override
6092 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006093 mArgs = createInstallArgs(this);
6094 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006095 }
Kenny Root6dceb882012-04-12 14:23:49 -07006096
6097 public boolean isForwardLocked() {
6098 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6099 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006100
6101 public Uri getPackageUri() {
6102 if (mTempPackage != null) {
6103 return Uri.fromFile(mTempPackage);
6104 } else {
6105 return mPackageURI;
6106 }
6107 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006108 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006109
6110 /*
6111 * Utility class used in movePackage api.
6112 * srcArgs and targetArgs are not set for invalid flags and make
6113 * sure to do null checks when invoking methods on them.
6114 * We probably want to return ErrorPrams for both failed installs
6115 * and moves.
6116 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006117 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006118 final IPackageMoveObserver observer;
6119 final int flags;
6120 final String packageName;
6121 final InstallArgs srcArgs;
6122 final InstallArgs targetArgs;
Kenny Root6dceb882012-04-12 14:23:49 -07006123 int uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006124 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07006125
6126 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
Kenny Root6dceb882012-04-12 14:23:49 -07006127 String packageName, String dataDir, int uid) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006128 this.srcArgs = srcArgs;
6129 this.observer = observer;
6130 this.flags = flags;
6131 this.packageName = packageName;
Kenny Root6dceb882012-04-12 14:23:49 -07006132 this.uid = uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006133 if (srcArgs != null) {
6134 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07006135 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006136 } else {
6137 targetArgs = null;
6138 }
6139 }
6140
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006141 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006142 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6143 // Check for storage space on target medium
6144 if (!targetArgs.checkFreeStorage(mContainerService)) {
6145 Log.w(TAG, "Insufficient storage to install");
6146 return;
6147 }
Kenny Rootbf023582012-05-02 16:56:15 -07006148
6149 mRet = srcArgs.doPreCopy();
6150 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6151 return;
6152 }
6153
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006154 mRet = targetArgs.copyApk(mContainerService, false);
Kenny Rootbf023582012-05-02 16:56:15 -07006155 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6156 srcArgs.doPostCopy(uid);
6157 return;
6158 }
6159
6160 mRet = srcArgs.doPostCopy(uid);
6161 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6162 return;
6163 }
6164
6165 mRet = targetArgs.doPreInstall(mRet);
6166 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6167 return;
6168 }
6169
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006170 if (DEBUG_SD_INSTALL) {
6171 StringBuilder builder = new StringBuilder();
6172 if (srcArgs != null) {
6173 builder.append("src: ");
6174 builder.append(srcArgs.getCodePath());
6175 }
6176 if (targetArgs != null) {
6177 builder.append(" target : ");
6178 builder.append(targetArgs.getCodePath());
6179 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006180 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006181 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006182 }
6183
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006184 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006185 void handleReturnCode() {
Kenny Root6dceb882012-04-12 14:23:49 -07006186 targetArgs.doPostInstall(mRet, uid);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006187 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
6188 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
6189 currentStatus = PackageManager.MOVE_SUCCEEDED;
6190 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
6191 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
6192 }
6193 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006194 }
6195
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006196 @Override
6197 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006198 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006199 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006200 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006201
Kenny Root6dceb882012-04-12 14:23:49 -07006202 /**
6203 * Used during creation of InstallArgs
6204 *
6205 * @param flags package installation flags
6206 * @return true if should be installed on external storage
6207 */
6208 private static boolean installOnSd(int flags) {
6209 if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
6210 return false;
6211 }
6212 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
6213 return true;
6214 }
6215 return false;
6216 }
6217
6218 /**
6219 * Used during creation of InstallArgs
6220 *
6221 * @param flags package installation flags
6222 * @return true if should be installed as forward locked
6223 */
6224 private static boolean installForwardLocked(int flags) {
6225 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6226 }
6227
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006228 private InstallArgs createInstallArgs(InstallParams params) {
Kenny Root6dceb882012-04-12 14:23:49 -07006229 if (installOnSd(params.flags) || params.isForwardLocked()) {
6230 return new AsecInstallArgs(params);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006231 } else {
6232 return new FileInstallArgs(params);
6233 }
6234 }
6235
Kenny Root85387d72010-08-26 10:13:11 -07006236 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
6237 String nativeLibraryPath) {
Kenny Root84e35ea2012-06-06 16:05:05 -07006238 final boolean isInAsec;
6239 if (installOnSd(flags)) {
6240 /* Apps on SD card are always in ASEC containers. */
6241 isInAsec = true;
6242 } else if (installForwardLocked(flags)
6243 && !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
6244 /*
6245 * Forward-locked apps are only in ASEC containers if they're the
6246 * new style
6247 */
6248 isInAsec = true;
6249 } else {
6250 isInAsec = false;
6251 }
6252
6253 if (isInAsec) {
Kenny Root6dceb882012-04-12 14:23:49 -07006254 return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07006255 installOnSd(flags), installForwardLocked(flags));
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006256 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006257 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006258 }
6259 }
6260
Kenny Root85387d72010-08-26 10:13:11 -07006261 // Used by package mover
6262 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Kenny Root6dceb882012-04-12 14:23:49 -07006263 if (installOnSd(flags) || installForwardLocked(flags)) {
Kenny Rootbf023582012-05-02 16:56:15 -07006264 String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
6265 + AsecInstallArgs.RES_FILE_NAME);
6266 return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
6267 installForwardLocked(flags));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006268 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006269 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006270 }
6271 }
6272
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006273 static abstract class InstallArgs {
6274 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006275 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006276 final int flags;
6277 final Uri packageURI;
6278 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07006279 final ManifestDigest manifestDigest;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006280
Kenny Root5ab21572011-07-27 11:11:19 -07006281 InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
6282 String installerPackageName, ManifestDigest manifestDigest) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006283 this.packageURI = packageURI;
6284 this.flags = flags;
6285 this.observer = observer;
6286 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07006287 this.manifestDigest = manifestDigest;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006288 }
6289
6290 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006291 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006292 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006293 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Kenny Root6dceb882012-04-12 14:23:49 -07006294
6295 abstract int doPostInstall(int status, int uid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006296 abstract String getCodePath();
6297 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07006298 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006299 // Need installer lock especially for dex file removal.
6300 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006301 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006302 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Kenny Root6dceb882012-04-12 14:23:49 -07006303
Kenny Rootbf023582012-05-02 16:56:15 -07006304 /**
6305 * Called before the source arguments are copied. This is used mostly
6306 * for MoveParams when it needs to read the source file to put it in the
6307 * destination.
6308 */
6309 int doPreCopy() {
6310 return PackageManager.INSTALL_SUCCEEDED;
6311 }
6312
6313 /**
6314 * Called after the source arguments are copied. This is used mostly for
6315 * MoveParams when it needs to read the source file to put it in the
6316 * destination.
6317 *
6318 * @return
6319 */
6320 int doPostCopy(int uid) {
6321 return PackageManager.INSTALL_SUCCEEDED;
6322 }
6323
Kenny Root6dceb882012-04-12 14:23:49 -07006324 protected boolean isFwdLocked() {
6325 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6326 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006327 }
6328
6329 class FileInstallArgs extends InstallArgs {
6330 File installDir;
6331 String codeFileName;
6332 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07006333 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006334 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006335
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006336 FileInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006337 super(params.getPackageUri(), params.observer, params.flags,
6338 params.installerPackageName, params.manifestDigest);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006339 }
6340
Kenny Root85387d72010-08-26 10:13:11 -07006341 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Kenny Root5ab21572011-07-27 11:11:19 -07006342 super(null, null, 0, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006343 File codeFile = new File(fullCodePath);
6344 installDir = codeFile.getParentFile();
6345 codeFileName = fullCodePath;
6346 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006347 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006348 }
6349
Kenny Root85387d72010-08-26 10:13:11 -07006350 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Kenny Root5ab21572011-07-27 11:11:19 -07006351 super(packageURI, null, 0, null, null);
Kenny Root85387d72010-08-26 10:13:11 -07006352 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006353 String apkName = getNextCodePath(null, pkgName, ".apk");
6354 codeFileName = new File(installDir, apkName + ".apk").getPath();
6355 resourceFileName = getResourcePathFromCodePath();
Kenny Root85387d72010-08-26 10:13:11 -07006356 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006357 }
6358
Kenny Root11128572010-10-11 10:51:32 -07006359 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07006360 final long lowThreshold;
6361
6362 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
6363 .getService(DeviceStorageMonitorService.SERVICE);
6364 if (dsm == null) {
6365 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
6366 lowThreshold = 0L;
6367 } else {
6368 if (dsm.isMemoryLow()) {
6369 Log.w(TAG, "Memory is reported as being too low; aborting package install");
6370 return false;
6371 }
6372
6373 lowThreshold = dsm.getMemoryLowThreshold();
6374 }
6375
Kenny Root11128572010-10-11 10:51:32 -07006376 try {
6377 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6378 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006379 return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07006380 } finally {
6381 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6382 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006383 }
6384
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006385 String getCodePath() {
6386 return codeFileName;
6387 }
6388
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006389 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07006390 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006391 codeFileName = createTempPackageFile(installDir).getPath();
6392 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006393 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006394 }
6395
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006396 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006397 if (temp) {
6398 // Generate temp file name
6399 createCopyFile();
6400 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006401 // Get a ParcelFileDescriptor to write to the output file
6402 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006403 if (!created) {
6404 try {
6405 codeFile.createNewFile();
6406 // Set permissions
6407 if (!setPermissions()) {
6408 // Failed setting permissions.
6409 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6410 }
6411 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006412 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006413 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6414 }
6415 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006416 ParcelFileDescriptor out = null;
6417 try {
Kenny Root85387d72010-08-26 10:13:11 -07006418 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006419 } catch (FileNotFoundException e) {
Kenny Rootf5121a92011-08-10 16:23:32 -07006420 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006421 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6422 }
6423 // Copy the resource now
6424 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6425 try {
Kenny Root11128572010-10-11 10:51:32 -07006426 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6427 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006428 ret = imcs.copyResource(packageURI, null, out);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006429 } finally {
Kenny Root2782a472012-04-14 21:48:21 -07006430 IoUtils.closeQuietly(out);
Kenny Root11128572010-10-11 10:51:32 -07006431 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006432 }
Kenny Root85387d72010-08-26 10:13:11 -07006433
Kenny Root2782a472012-04-14 21:48:21 -07006434 if (isFwdLocked()) {
6435 final File destResourceFile = new File(getResourcePath());
6436
6437 // Copy the public files
6438 try {
6439 PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
6440 } catch (IOException e) {
6441 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
6442 + " forward-locked app.");
6443 destResourceFile.delete();
6444 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6445 }
6446 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006447 return ret;
6448 }
6449
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006450 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006451 if (status != PackageManager.INSTALL_SUCCEEDED) {
6452 cleanUp();
6453 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006454 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006455 }
6456
6457 boolean doRename(int status, final String pkgName, String oldCodePath) {
6458 if (status != PackageManager.INSTALL_SUCCEEDED) {
6459 cleanUp();
6460 return false;
6461 } else {
Kenny Root2782a472012-04-14 21:48:21 -07006462 final File oldCodeFile = new File(getCodePath());
6463 final File oldResourceFile = new File(getResourcePath());
6464
6465 // Rename APK file based on packageName
6466 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
6467 final File newCodeFile = new File(installDir, apkName + ".apk");
6468 if (!oldCodeFile.renameTo(newCodeFile)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006469 return false;
6470 }
Kenny Root2782a472012-04-14 21:48:21 -07006471 codeFileName = newCodeFile.getPath();
6472
6473 // Rename public resource file if it's forward-locked.
6474 final File newResFile = new File(getResourcePathFromCodePath());
6475 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
6476 return false;
6477 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006478 resourceFileName = getResourcePathFromCodePath();
Kenny Root2782a472012-04-14 21:48:21 -07006479
6480 // Attempt to set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006481 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006482 return false;
6483 }
Kenny Root2782a472012-04-14 21:48:21 -07006484
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006485 return true;
6486 }
6487 }
6488
Kenny Root6dceb882012-04-12 14:23:49 -07006489 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006490 if (status != PackageManager.INSTALL_SUCCEEDED) {
6491 cleanUp();
6492 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006493 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006494 }
6495
6496 String getResourcePath() {
6497 return resourceFileName;
6498 }
6499
Kenny Root2782a472012-04-14 21:48:21 -07006500 private String getResourcePathFromCodePath() {
6501 final String codePath = getCodePath();
6502 if (isFwdLocked()) {
6503 final StringBuilder sb = new StringBuilder();
6504
6505 sb.append(mAppInstallDir.getPath());
6506 sb.append('/');
6507 sb.append(getApkName(codePath));
6508 sb.append(".zip");
6509
6510 /*
6511 * If our APK is a temporary file, mark the resource as a
6512 * temporary file as well so it can be cleaned up after
6513 * catastrophic failure.
6514 */
6515 if (codePath.endsWith(".tmp")) {
6516 sb.append(".tmp");
6517 }
6518
6519 return sb.toString();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006520 } else {
6521 return codePath;
6522 }
6523 }
6524
Kenny Root85387d72010-08-26 10:13:11 -07006525 @Override
6526 String getNativeLibraryPath() {
6527 return libraryPath;
6528 }
6529
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006530 private boolean cleanUp() {
6531 boolean ret = true;
6532 String sourceDir = getCodePath();
6533 String publicSourceDir = getResourcePath();
6534 if (sourceDir != null) {
6535 File sourceFile = new File(sourceDir);
6536 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006537 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006538 ret = false;
6539 }
6540 // Delete application's code and resources
6541 sourceFile.delete();
6542 }
6543 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
6544 final File publicSourceFile = new File(publicSourceDir);
6545 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006546 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006547 }
6548 if (publicSourceFile.exists()) {
6549 publicSourceFile.delete();
6550 }
6551 }
6552 return ret;
6553 }
6554
6555 void cleanUpResourcesLI() {
6556 String sourceDir = getCodePath();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07006557 if (cleanUp()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006558 int retCode = mInstaller.rmdex(sourceDir);
6559 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006560 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006561 + " at location "
6562 + sourceDir + ", retcode=" + retCode);
6563 // we don't consider this to be a failure of the core package deletion
6564 }
6565 }
6566 }
6567
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006568 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006569 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07006570 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006571 final int filePermissions =
6572 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
6573 |FileUtils.S_IROTH;
6574 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
6575 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006576 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006577 getCodePath()
6578 + ". The return code was: " + retCode);
6579 // TODO Define new internal error
6580 return false;
6581 }
6582 return true;
6583 }
6584 return true;
6585 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006586
6587 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07006588 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006589 cleanUpResourcesLI();
6590 return true;
6591 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006592 }
6593
Kenny Root51a573c2012-05-17 13:30:28 -07006594 private boolean isAsecExternal(String cid) {
6595 final String asecPath = PackageHelper.getSdFilesystem(cid);
6596 return !asecPath.startsWith(mAsecInternalPath);
6597 }
6598
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07006599 /**
6600 * Extract the MountService "container ID" from the full code path of an
6601 * .apk.
6602 */
6603 static String cidFromCodePath(String fullCodePath) {
6604 int eidx = fullCodePath.lastIndexOf("/");
6605 String subStr1 = fullCodePath.substring(0, eidx);
6606 int sidx = subStr1.lastIndexOf("/");
6607 return subStr1.substring(sidx+1, eidx);
6608 }
6609
Kenny Root6dceb882012-04-12 14:23:49 -07006610 class AsecInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006611 static final String RES_FILE_NAME = "pkg.apk";
Kenny Root6dceb882012-04-12 14:23:49 -07006612 static final String PUBLIC_RES_FILE_NAME = "res.zip";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006613
Kenny Root85387d72010-08-26 10:13:11 -07006614 String cid;
6615 String packagePath;
Kenny Root6dceb882012-04-12 14:23:49 -07006616 String resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006617 String libraryPath;
6618
Kenny Root6dceb882012-04-12 14:23:49 -07006619 AsecInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006620 super(params.getPackageUri(), params.observer, params.flags,
6621 params.installerPackageName, params.manifestDigest);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006622 }
6623
Kenny Root6dceb882012-04-12 14:23:49 -07006624 AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07006625 boolean isExternal, boolean isForwardLocked) {
6626 super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
6627 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006628 // Extract cid from fullCodePath
6629 int eidx = fullCodePath.lastIndexOf("/");
6630 String subStr1 = fullCodePath.substring(0, eidx);
6631 int sidx = subStr1.lastIndexOf("/");
6632 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07006633 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006634 }
6635
Kenny Rootc7a89992012-06-05 15:13:17 -07006636 AsecInstallArgs(String cid, boolean isForwardLocked) {
6637 super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
6638 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Dianne Hackbornaa77de12010-05-14 22:33:54 -07006639 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07006640 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006641 }
6642
Kenny Rootbf023582012-05-02 16:56:15 -07006643 AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
6644 super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
6645 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006646 this.cid = cid;
6647 }
6648
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006649 void createCopyFile() {
6650 cid = getTempContainerId();
6651 }
6652
Kenny Root11128572010-10-11 10:51:32 -07006653 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
6654 try {
6655 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6656 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006657 return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07006658 } finally {
6659 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6660 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006661 }
6662
Kenny Root6dceb882012-04-12 14:23:49 -07006663 private final boolean isExternal() {
6664 return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
6665 }
6666
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006667 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006668 if (temp) {
6669 createCopyFile();
Kenny Rootf5121a92011-08-10 16:23:32 -07006670 } else {
6671 /*
6672 * Pre-emptively destroy the container since it's destroyed if
6673 * copying fails due to it existing anyway.
6674 */
6675 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006676 }
Kenny Root11128572010-10-11 10:51:32 -07006677
6678 final String newCachePath;
6679 try {
6680 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6681 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006682 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
6683 RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07006684 } finally {
6685 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6686 }
6687
Kenny Root85387d72010-08-26 10:13:11 -07006688 if (newCachePath != null) {
6689 setCachePath(newCachePath);
6690 return PackageManager.INSTALL_SUCCEEDED;
6691 } else {
6692 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6693 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006694 }
6695
6696 @Override
6697 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07006698 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006699 }
6700
6701 @Override
6702 String getResourcePath() {
Kenny Root6dceb882012-04-12 14:23:49 -07006703 return resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006704 }
6705
6706 @Override
6707 String getNativeLibraryPath() {
6708 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006709 }
6710
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006711 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006712 if (status != PackageManager.INSTALL_SUCCEEDED) {
6713 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006714 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006715 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006716 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006717 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07006718 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
6719 Process.SYSTEM_UID);
6720 if (newCachePath != null) {
6721 setCachePath(newCachePath);
6722 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006723 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6724 }
6725 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006726 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006727 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006728 }
6729
6730 boolean doRename(int status, final String pkgName,
6731 String oldCodePath) {
6732 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006733 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006734 if (PackageHelper.isContainerMounted(cid)) {
6735 // Unmount the container
6736 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006737 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006738 return false;
6739 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006740 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006741 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07006742 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
6743 " which might be stale. Will try to clean up.");
6744 // Clean up the stale container and proceed to recreate.
6745 if (!PackageHelper.destroySdDir(newCacheId)) {
6746 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
6747 return false;
6748 }
6749 // Successfully cleaned up stale container. Try to rename again.
6750 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
6751 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
6752 + " inspite of cleaning it up.");
6753 return false;
6754 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006755 }
6756 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006757 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006758 newCachePath = PackageHelper.mountSdDir(newCacheId,
6759 getEncryptKey(), Process.SYSTEM_UID);
6760 } else {
6761 newCachePath = PackageHelper.getSdDir(newCacheId);
6762 }
6763 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006764 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006765 return false;
6766 }
6767 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07006768 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006769 " at new path: " + newCachePath);
6770 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07006771 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006772 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006773 }
6774
Kenny Root85387d72010-08-26 10:13:11 -07006775 private void setCachePath(String newCachePath) {
6776 File cachePath = new File(newCachePath);
6777 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
6778 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
Kenny Root6dceb882012-04-12 14:23:49 -07006779
6780 if (isFwdLocked()) {
6781 resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
6782 } else {
6783 resourcePath = packagePath;
6784 }
Kenny Root85387d72010-08-26 10:13:11 -07006785 }
6786
Kenny Root6dceb882012-04-12 14:23:49 -07006787 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006788 if (status != PackageManager.INSTALL_SUCCEEDED) {
6789 cleanUp();
6790 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07006791 final int groupOwner;
6792 final String protectedFile;
6793 if (isFwdLocked()) {
6794 groupOwner = uid;
6795 protectedFile = RES_FILE_NAME;
6796 } else {
6797 groupOwner = -1;
6798 protectedFile = null;
6799 }
6800
Kenny Root6dceb882012-04-12 14:23:49 -07006801 if (uid < Process.FIRST_APPLICATION_UID
Kenny Rootbf023582012-05-02 16:56:15 -07006802 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Kenny Root6dceb882012-04-12 14:23:49 -07006803 Slog.e(TAG, "Failed to finalize " + cid);
6804 PackageHelper.destroySdDir(cid);
6805 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6806 }
6807
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006808 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006809 if (!mounted) {
Kenny Root6dceb882012-04-12 14:23:49 -07006810 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006811 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006812 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006813 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006814 }
6815
6816 private void cleanUp() {
Kenny Root6dceb882012-04-12 14:23:49 -07006817 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
6818
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006819 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006820 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006821 }
6822
6823 void cleanUpResourcesLI() {
6824 String sourceFile = getCodePath();
6825 // Remove dex file
Jeff Brown5d6d90f2011-07-11 13:04:53 -07006826 int retCode = mInstaller.rmdex(sourceFile);
6827 if (retCode < 0) {
6828 Slog.w(TAG, "Couldn't remove dex file for package: "
6829 + " at location "
6830 + sourceFile.toString() + ", retcode=" + retCode);
6831 // we don't consider this to be a failure of the core package deletion
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006832 }
6833 cleanUp();
6834 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006835
6836 boolean matchContainer(String app) {
6837 if (cid.startsWith(app)) {
6838 return true;
6839 }
6840 return false;
6841 }
6842
6843 String getPackageName() {
Kenny Rootc7a89992012-06-05 15:13:17 -07006844 return getAsecPackageName(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006845 }
6846
6847 boolean doPostDeleteLI(boolean delete) {
6848 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006849 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006850 if (mounted) {
6851 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006852 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006853 }
6854 if (ret && delete) {
6855 cleanUpResourcesLI();
6856 }
6857 return ret;
6858 }
Kenny Rootbf023582012-05-02 16:56:15 -07006859
6860 @Override
6861 int doPreCopy() {
6862 if (isFwdLocked()) {
6863 if (!PackageHelper.fixSdPermissions(cid,
6864 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
6865 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6866 }
6867 }
6868
6869 return PackageManager.INSTALL_SUCCEEDED;
6870 }
6871
6872 @Override
6873 int doPostCopy(int uid) {
6874 if (isFwdLocked()) {
Kenny Rootbf023582012-05-02 16:56:15 -07006875 if (uid < Process.FIRST_APPLICATION_UID
6876 || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) {
6877 Slog.e(TAG, "Failed to finalize " + cid);
6878 PackageHelper.destroySdDir(cid);
6879 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6880 }
6881 }
6882
6883 return PackageManager.INSTALL_SUCCEEDED;
6884 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006885 };
6886
Kenny Rootc7a89992012-06-05 15:13:17 -07006887 static String getAsecPackageName(String packageCid) {
6888 int idx = packageCid.lastIndexOf("-");
6889 if (idx == -1) {
6890 return packageCid;
6891 }
6892 return packageCid.substring(0, idx);
6893 }
6894
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006895 // Utility method used to create code paths based on package name and available index.
6896 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
6897 String idxStr = "";
6898 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006899 // Fall back to default value of idx=1 if prefix is not
6900 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006901 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00006902 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006903 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00006904 if (subStr.endsWith(suffix)) {
6905 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006906 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006907 // If oldCodePath already contains prefix find out the
6908 // ending index to either increment or decrement.
6909 int sidx = subStr.lastIndexOf(prefix);
6910 if (sidx != -1) {
6911 subStr = subStr.substring(sidx + prefix.length());
6912 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006913 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
6914 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006915 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006916 try {
6917 idx = Integer.parseInt(subStr);
6918 if (idx <= 1) {
6919 idx++;
6920 } else {
6921 idx--;
6922 }
6923 } catch(NumberFormatException e) {
6924 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006925 }
6926 }
6927 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006928 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006929 return prefix + idxStr;
6930 }
6931
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006932 // Utility method used to ignore ADD/REMOVE events
6933 // by directory observer.
6934 private static boolean ignoreCodePath(String fullPathStr) {
6935 String apkName = getApkName(fullPathStr);
6936 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
6937 if (idx != -1 && ((idx+1) < apkName.length())) {
6938 // Make sure the package ends with a numeral
6939 String version = apkName.substring(idx+1);
6940 try {
6941 Integer.parseInt(version);
6942 return true;
6943 } catch (NumberFormatException e) {}
6944 }
6945 return false;
6946 }
6947
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006948 // Utility method that returns the relative package path with respect
6949 // to the installation directory. Like say for /data/data/com.test-1.apk
6950 // string com.test-1 is returned.
6951 static String getApkName(String codePath) {
6952 if (codePath == null) {
6953 return null;
6954 }
6955 int sidx = codePath.lastIndexOf("/");
6956 int eidx = codePath.lastIndexOf(".");
6957 if (eidx == -1) {
6958 eidx = codePath.length();
6959 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006960 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006961 return null;
6962 }
6963 return codePath.substring(sidx+1, eidx);
6964 }
6965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006966 class PackageInstalledInfo {
6967 String name;
6968 int uid;
6969 PackageParser.Package pkg;
6970 int returnCode;
6971 PackageRemovedInfo removedInfo;
6972 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 /*
6975 * Install a non-existing package.
6976 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006977 private void installNewPackageLI(PackageParser.Package pkg,
6978 int parseFlags,
6979 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02006980 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006981 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006982 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08006983
Amith Yamasani0b285492011-04-14 17:35:23 -07006984 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 res.name = pkgName;
6986 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07006987 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
6988 // A package with the same name is already installed, though
6989 // it has been renamed to an older name. The package we
6990 // are trying to install should be installed as an update to
6991 // the existing one, but that has not been requested, so bail.
6992 Slog.w(TAG, "Attempt to re-install " + pkgName
6993 + " without first uninstalling package running as "
6994 + mSettings.mRenamedPackages.get(pkgName));
6995 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6996 return;
6997 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006998 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006999 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007000 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007001 + " without first uninstalling.");
7002 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
7003 return;
7004 }
7005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007007 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
7008 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007009 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007010 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7012 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
7013 }
7014 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007015 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007016 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007017 res);
7018 // delete the partially installed application. the data directory will have to be
7019 // restored if it was already existing
7020 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
7021 // remove package from internal structures. Note that we want deletePackageX to
7022 // delete the package data and cache directories that it created in
7023 // scanPackageLocked, unless those directories existed before we even tried to
7024 // install.
7025 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007026 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007028 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 }
7030 }
7031 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007032
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007033 private void replacePackageLI(PackageParser.Package pkg,
7034 int parseFlags,
7035 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02007036 String installerPackageName, PackageInstalledInfo res) {
7037
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007038 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007039 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007040 // First find the old package info and check signatures
7041 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007042 oldPackage = mPackages.get(pkgName);
Kenny Root447106f2011-03-23 11:00:15 -07007043 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07007044 != PackageManager.SIGNATURE_MATCH) {
Kenny Root8c11f1d2012-04-14 12:10:38 -07007045 Slog.w(TAG, "New package has a different signature: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
7047 return;
7048 }
7049 }
Kenny Root85387d72010-08-26 10:13:11 -07007050 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007051 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007052 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007054 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007055 }
7056 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007059 PackageParser.Package pkg,
7060 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02007061 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 PackageParser.Package newPackage = null;
7063 String pkgName = deletedPackage.packageName;
7064 boolean deletedPkg = true;
7065 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007066
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007067 long origUpdateTime;
7068 if (pkg.mExtras != null) {
7069 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
7070 } else {
7071 origUpdateTime = 0;
7072 }
7073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007075 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007076 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007077 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
7079 deletedPkg = false;
7080 } else {
7081 // Successfully deleted the old package. Now proceed with re-installation
7082 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007083 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
7084 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007086 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7088 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08007089 }
7090 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007091 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007092 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 res);
7094 updatedSettings = true;
7095 }
7096 }
7097
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007098 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 // remove package from internal structures. Note that we want deletePackageX to
7100 // delete the package data and cache directories that it created in
7101 // scanPackageLocked, unless those directories existed before we even tried to
7102 // install.
7103 if(updatedSettings) {
7104 deletePackageLI(
7105 pkgName, true,
7106 PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007107 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 }
7109 // Since we failed to install the new package we need to restore the old
7110 // package that we deleted.
7111 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007112 File restoreFile = new File(deletedPackage.mPath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007113 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007114 boolean oldOnSd = isExternal(deletedPackage);
7115 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
7116 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
7117 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007118 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
7119 | SCAN_UPDATE_TIME;
7120 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
7121 origUpdateTime) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007122 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
7123 return;
7124 }
7125 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07007126 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007127 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007128 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08007129 UPDATE_PERMISSIONS_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07007130 // can downgrade to reader
7131 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007132 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007133 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 }
7135 }
7136 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007139 PackageParser.Package pkg,
7140 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02007141 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 PackageParser.Package newPackage = null;
7143 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007144 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 PackageParser.PARSE_IS_SYSTEM;
7146 String packageName = deletedPackage.packageName;
7147 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
7148 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007149 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 return;
7151 }
7152 PackageParser.Package oldPkg;
7153 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07007154 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 synchronized (mPackages) {
7156 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007157 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
7159 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007160 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 return;
7162 }
7163 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007164
7165 killApplication(packageName, oldPkg.applicationInfo.uid);
7166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 res.removedInfo.uid = oldPkg.applicationInfo.uid;
7168 res.removedInfo.removedPackage = packageName;
7169 // Remove existing system package
7170 removePackageLI(oldPkg, true);
Kenny Root447106f2011-03-23 11:00:15 -07007171 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08007172 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007173 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007174 // We didn't need to disable the .apk as a current system package,
7175 // which means we are replacing another update that is already
7176 // installed. We need to make sure to delete the older one's .apk.
Kenny Root6dceb882012-04-12 14:23:49 -07007177 res.removedInfo.args = createInstallArgs(0,
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007178 deletedPackage.applicationInfo.sourceDir,
7179 deletedPackage.applicationInfo.publicSourceDir,
7180 deletedPackage.applicationInfo.nativeLibraryDir);
7181 } else {
7182 res.removedInfo.args = null;
7183 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08007184 }
7185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 // Successfully disabled the old package. Now proceed with re-installation
7187 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
7188 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007189 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007191 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7193 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
7194 }
7195 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007196 if (newPackage.mExtras != null) {
7197 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
7198 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
7199 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
7200 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007201 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202 updatedSettings = true;
7203 }
7204
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007205 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 // Re installation failed. Restore old information
7207 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07007208 if (newPackage != null) {
7209 removePackageLI(newPackage, true);
7210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 // Add back the old system package
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007212 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 // Restore the old system information in Settings
7214 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007215 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07007216 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02007217 mSettings.setInstallerPackageName(packageName,
7218 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 }
Kenny Root447106f2011-03-23 11:00:15 -07007220 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 }
7222 }
7223 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007224
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007225 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007226 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007227 int retCode;
7228 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
7229 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
7230 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07007231 if (mNoDexOpt) {
7232 /*
7233 * If we're in an engineering build, programs are lazily run
7234 * through dexopt. If the .dex file doesn't exist yet, it
7235 * will be created when the program is run next.
7236 */
7237 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
7238 } else {
7239 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
7240 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7241 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007242 }
7243 }
7244 return PackageManager.INSTALL_SUCCEEDED;
7245 }
7246
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007247 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007248 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007249 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 synchronized (mPackages) {
7251 //write settings. the installStatus will be incomplete at this stage.
7252 //note that the new package setting would have already been
7253 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07007254 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07007255 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 }
7257
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007258 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007259 != PackageManager.INSTALL_SUCCEEDED) {
7260 // Discontinue if moving dex files failed.
7261 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 }
Kenny Root6dceb882012-04-12 14:23:49 -07007263
7264 Log.d(TAG, "New package installed in " + newPackage.mPath);
7265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007267 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08007268 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
7269 ? UPDATE_PERMISSIONS_ALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 res.name = pkgName;
7271 res.uid = newPackage.applicationInfo.uid;
7272 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07007273 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02007274 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
7276 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07007277 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 }
7279 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007280
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007281 private void installPackageLI(InstallArgs args,
7282 boolean newInstall, PackageInstalledInfo res) {
7283 int pFlags = args.flags;
7284 String installerPackageName = args.installerPackageName;
7285 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007286 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007287 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007288 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007289 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007290 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007291 // Result object to be returned
7292 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
7293
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007294 // Retrieve PackageSettings and parse package
Kenny Root6dceb882012-04-12 14:23:49 -07007295 int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
7296 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
7297 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007298 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
7299 pp.setSeparateProcesses(mSeparateProcesses);
7300 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
7301 null, mMetrics, parseFlags);
7302 if (pkg == null) {
7303 res.returnCode = pp.getParseError();
7304 return;
7305 }
7306 String pkgName = res.name = pkg.packageName;
7307 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
7308 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
7309 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
7310 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007311 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007312 }
7313 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
7314 res.returnCode = pp.getParseError();
7315 return;
7316 }
Kenny Root5ab21572011-07-27 11:11:19 -07007317
7318 /* If the installer passed in a manifest digest, compare it now. */
7319 if (args.manifestDigest != null) {
7320 if (DEBUG_INSTALL) {
7321 final String parsedManifest = pkg.manifestDigest == null ? "null"
7322 : pkg.manifestDigest.toString();
7323 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
7324 + parsedManifest);
7325 }
7326
7327 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
7328 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
7329 return;
7330 }
7331 } else if (DEBUG_INSTALL) {
7332 final String parsedManifest = pkg.manifestDigest == null
7333 ? "null" : pkg.manifestDigest.toString();
7334 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
7335 }
7336
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007337 // Get rid of all references to package scan path via parser.
7338 pp = null;
7339 String oldCodePath = null;
7340 boolean systemApp = false;
7341 synchronized (mPackages) {
7342 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007343 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
7344 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08007345 if (pkg.mOriginalPackages != null
7346 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007347 && mPackages.containsKey(oldName)) {
7348 // This package is derived from an original package,
7349 // and this device has been updating from that original
7350 // name. We must continue using the original name, so
7351 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08007352 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007353 pkgName = pkg.packageName;
7354 replace = true;
7355 } else if (mPackages.containsKey(pkgName)) {
7356 // This package, under its official name, already exists
7357 // on the device; we should replace it.
7358 replace = true;
7359 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007360 }
7361 PackageSetting ps = mSettings.mPackages.get(pkgName);
7362 if (ps != null) {
7363 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
7364 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
7365 systemApp = (ps.pkg.applicationInfo.flags &
7366 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07007367 }
7368 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007369 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007370
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007371 if (systemApp && onSd) {
7372 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007373 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007374 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
7375 return;
7376 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08007377
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007378 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
7379 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7380 return;
7381 }
7382 // Set application objects path explicitly after the rename
7383 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07007384 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007385 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007386 replacePackageLI(pkg, parseFlags, scanMode,
7387 installerPackageName, res);
7388 } else {
7389 installNewPackageLI(pkg, parseFlags, scanMode,
7390 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 }
7392 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007393
Kenny Root85387d72010-08-26 10:13:11 -07007394 private static boolean isForwardLocked(PackageParser.Package pkg) {
7395 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007396 }
7397
Kenny Root88670d82012-05-09 15:47:35 -07007398
7399 private boolean isForwardLocked(PackageSetting ps) {
7400 return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
7401 }
7402
Kenny Root85387d72010-08-26 10:13:11 -07007403 private static boolean isExternal(PackageParser.Package pkg) {
7404 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
7405 }
7406
Kenny Root6dceb882012-04-12 14:23:49 -07007407 private static boolean isExternal(PackageSetting ps) {
7408 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
7409 }
7410
Kenny Root85387d72010-08-26 10:13:11 -07007411 private static boolean isSystemApp(PackageParser.Package pkg) {
7412 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
7413 }
7414
Kenny Root502e9a42011-01-10 13:48:15 -08007415 private static boolean isSystemApp(ApplicationInfo info) {
7416 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
7417 }
7418
Kenny Root208d3412012-05-07 19:42:35 -07007419 private static boolean isSystemApp(PackageSetting ps) {
7420 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
7421 }
7422
Kenny Root85387d72010-08-26 10:13:11 -07007423 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
7424 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007425 }
7426
Kenny Root88670d82012-05-09 15:47:35 -07007427 private int packageFlagsToInstallFlags(PackageSetting ps) {
7428 int installFlags = 0;
7429 if (isExternal(ps)) {
7430 installFlags |= PackageManager.INSTALL_EXTERNAL;
7431 }
7432 if (isForwardLocked(ps)) {
7433 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
7434 }
7435 return installFlags;
7436 }
7437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 private void deleteTempPackageFiles() {
7439 FilenameFilter filter = new FilenameFilter() {
7440 public boolean accept(File dir, String name) {
7441 return name.startsWith("vmdl") && name.endsWith(".tmp");
7442 }
7443 };
7444 String tmpFilesList[] = mAppInstallDir.list(filter);
7445 if(tmpFilesList == null) {
7446 return;
7447 }
7448 for(int i = 0; i < tmpFilesList.length; i++) {
7449 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
7450 tmpFile.delete();
7451 }
7452 }
7453
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007454 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 File tmpPackageFile;
7456 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007457 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007459 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 return null;
7461 }
7462 try {
7463 FileUtils.setPermissions(
7464 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
7465 -1, -1);
7466 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007467 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 return null;
7469 }
7470 return tmpPackageFile;
7471 }
7472
7473 public void deletePackage(final String packageName,
7474 final IPackageDeleteObserver observer,
7475 final int flags) {
7476 mContext.enforceCallingOrSelfPermission(
7477 android.Manifest.permission.DELETE_PACKAGES, null);
7478 // Queue up an async operation since the package deletion may take a little while.
7479 mHandler.post(new Runnable() {
7480 public void run() {
7481 mHandler.removeCallbacks(this);
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007482 final int returnCode = deletePackageX(packageName, true, true, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 if (observer != null) {
7484 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007485 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 } catch (RemoteException e) {
7487 Log.i(TAG, "Observer no longer exists.");
7488 } //end catch
7489 } //end if
7490 } //end run
7491 });
7492 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 /**
7495 * This method is an internal method that could be get invoked either
7496 * to delete an installed package or to clean up a failed installation.
7497 * After deleting an installed package, a broadcast is sent to notify any
7498 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007499 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007500 * installation wouldn't have sent the initial broadcast either
7501 * The key steps in deleting a package are
7502 * deleting the package information in internal structures like mPackages,
7503 * deleting the packages base directories through installd
7504 * updating mSettings to reflect current status
7505 * persisting settings for later use
7506 * sending a broadcast if necessary
7507 */
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007508 private int deletePackageX(String packageName, boolean sendBroadCast,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 boolean deleteCodeAndResources, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007510 final PackageRemovedInfo info = new PackageRemovedInfo();
7511 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007513 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
7514 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
7515 try {
7516 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007517 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007518 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007519 }
7520 } catch (RemoteException e) {
7521 }
7522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 synchronized (mInstallLock) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007524 res = deletePackageLI(packageName, deleteCodeAndResources,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007525 flags | REMOVE_CHATTY, info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007526 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007527
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007528 if (res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07007529 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007530 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
Romain Guy96f43572009-03-24 20:27:49 -07007531
7532 // If the removed package was a system update, the old system packaged
7533 // was re-enabled; we need to broadcast this information
7534 if (systemUpdate) {
7535 Bundle extras = new Bundle(1);
7536 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
7537 extras.putBoolean(Intent.EXTRA_REPLACING, true);
7538
Dianne Hackborne7f97212011-02-24 14:40:20 -08007539 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
Amith Yamasani13593602012-03-22 16:16:17 -07007540 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007541 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
Amith Yamasani13593602012-03-22 16:16:17 -07007542 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007543 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
Amith Yamasani13593602012-03-22 16:16:17 -07007544 null, packageName, null, UserId.USER_ALL);
Romain Guy96f43572009-03-24 20:27:49 -07007545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007547 // Force a gc here.
7548 Runtime.getRuntime().gc();
7549 // Delete the resources here after sending the broadcast to let
7550 // other processes clean up before deleting resources.
7551 if (info.args != null) {
7552 synchronized (mInstallLock) {
7553 info.args.doPostDeleteLI(deleteCodeAndResources);
7554 }
7555 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007556
7557 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 }
7559
7560 static class PackageRemovedInfo {
7561 String removedPackage;
7562 int uid = -1;
7563 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07007564 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007565 // Clean up resources deleted packages.
7566 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07007567
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007568 void sendBroadcast(boolean fullRemove, boolean replacing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 Bundle extras = new Bundle(1);
7570 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
7571 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
7572 if (replacing) {
7573 extras.putBoolean(Intent.EXTRA_REPLACING, true);
7574 }
7575 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08007576 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07007577 extras, null, null, UserId.USER_ALL);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07007578 if (fullRemove && !replacing) {
7579 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07007580 extras, null, null, UserId.USER_ALL);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07007581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007582 }
7583 if (removedUid >= 0) {
Amith Yamasani13593602012-03-22 16:16:17 -07007584 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
7585 UserId.getUserId(removedUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 }
7587 }
7588 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 /*
7591 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
7592 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007593 * 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 -08007594 * delete a partially installed application.
7595 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007596 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007597 int flags, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007599 if (outInfo != null) {
7600 outInfo.removedPackage = packageName;
7601 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007602 removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07007604 final PackageSetting deletedPs;
7605 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 synchronized (mPackages) {
7607 deletedPs = mSettings.mPackages.get(packageName);
7608 }
7609 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007610 int retCode = mInstaller.remove(packageName, 0);
7611 if (retCode < 0) {
7612 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
7613 + packageName + ", retcode=" + retCode);
7614 // we don't consider this to be a failure of the core package deletion
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 } else {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007616 // TODO: Kill the processes first
Amith Yamasani13593602012-03-22 16:16:17 -07007617 sUserManager.removePackageForAllUsers(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 }
Dianne Hackbornfb1f1032010-07-29 13:57:56 -07007619 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620 }
Kenny Root447106f2011-03-23 11:00:15 -07007621 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007622 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007623 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007624 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
7625 if (outInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007626 outInfo.removedUid = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007627 }
7628 if (deletedPs != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08007629 updatePermissionsLPw(deletedPs.name, null, 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007630 if (deletedPs.sharedUser != null) {
7631 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07007632 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007633 }
7634 }
Dianne Hackborn04505102012-02-29 12:34:04 -08007635 clearPackagePreferredActivitiesLPw(deletedPs.name);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007636 }
7637 }
Kenny Root447106f2011-03-23 11:00:15 -07007638 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007639 if (writeSettings) {
7640 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07007641 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 }
7644 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 /*
7647 * Tries to delete system package.
7648 */
7649 private boolean deleteSystemPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007650 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007651 ApplicationInfo applicationInfo = p.applicationInfo;
7652 //applicable for non-partially installed applications only
7653 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007654 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 return false;
7656 }
7657 PackageSetting ps = null;
7658 // Confirm if the system package has been updated
7659 // An updated system app can be deleted. This will also have to restore
7660 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07007661 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007663 ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007664 }
7665 if (ps == null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007666 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667 return false;
7668 } else {
7669 Log.i(TAG, "Deleting system pkg from data partition");
7670 }
7671 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07007672 outInfo.isRemovedPackageSystemUpdate = true;
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007673 if (ps.versionCode < p.mVersionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007674 // Delete data for downgrades
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007675 flags &= ~PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007676 } else {
7677 // Preserve data by setting flag
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007678 flags |= PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007679 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007680 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007681 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 if (!ret) {
7683 return false;
7684 }
Kenny Root447106f2011-03-23 11:00:15 -07007685 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007686 synchronized (mPackages) {
7687 // Reinstate the old system package
Kenny Root447106f2011-03-23 11:00:15 -07007688 mSettings.enableSystemPackageLPw(p.packageName);
Kenny Root8f7cc022010-09-12 09:04:56 -07007689 // Remove any native libraries from the upgraded package.
7690 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007691 }
7692 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007693 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007695 SCAN_MONITOR | SCAN_NO_PATHS, 0);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007698 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 return false;
7700 }
Kenny Root447106f2011-03-23 11:00:15 -07007701 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 synchronized (mPackages) {
Dianne Hackborne639da72012-02-21 15:11:13 -08007703 updatePermissionsLPw(newPkg.packageName, newPkg,
7704 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
Kenny Root447106f2011-03-23 11:00:15 -07007705 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007706 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07007707 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 }
7710 return true;
7711 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 private boolean deleteInstalledPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007714 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
7715 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 ApplicationInfo applicationInfo = p.applicationInfo;
7717 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007718 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 return false;
7720 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007721 if (outInfo != null) {
7722 outInfo.uid = applicationInfo.uid;
7723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007724
7725 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007726 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727
7728 // Delete application code and resources
7729 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007730 // TODO can pick up from PackageSettings as well
Kenny Root85387d72010-08-26 10:13:11 -07007731 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
7732 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
7733 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
7734 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 }
7736 return true;
7737 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 /*
7740 * This method handles package deletion in general
7741 */
7742 private boolean deletePackageLI(String packageName,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007743 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
7744 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007746 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007747 return false;
7748 }
7749 PackageParser.Package p;
7750 boolean dataOnly = false;
7751 synchronized (mPackages) {
7752 p = mPackages.get(packageName);
7753 if (p == null) {
7754 //this retrieves partially installed apps
7755 dataOnly = true;
7756 PackageSetting ps = mSettings.mPackages.get(packageName);
7757 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007758 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007759 return false;
7760 }
7761 p = ps.pkg;
7762 }
7763 }
7764 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007765 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007766 return false;
7767 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 if (dataOnly) {
7770 // Delete application data first
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007771 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 return true;
7773 }
7774 // At this point the package should have ApplicationInfo associated with it
7775 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007776 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 return false;
7778 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007779 boolean ret = false;
Kenny Root85387d72010-08-26 10:13:11 -07007780 if (isSystemApp(p)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 Log.i(TAG, "Removing system package:"+p.packageName);
7782 // When an updated system application is deleted we delete the existing resources as well and
7783 // fall back to existing code in system partition
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007784 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007785 } else {
7786 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007787 // Kill application pre-emptively especially for apps on sd.
7788 killApplication(packageName, p.applicationInfo.uid);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007789 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
7790 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007792 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007794
Dianne Hackborn183ce022012-06-29 15:00:21 -07007795 private final class ClearStorageConnection implements ServiceConnection {
7796 IMediaContainerService mContainerService;
7797
7798 @Override
7799 public void onServiceConnected(ComponentName name, IBinder service) {
7800 synchronized (this) {
7801 mContainerService = IMediaContainerService.Stub.asInterface(service);
7802 notifyAll();
7803 }
7804 }
7805
7806 @Override
7807 public void onServiceDisconnected(ComponentName name) {
7808 }
7809 }
7810
7811 private void clearExternalStorageDataSync(String packageName, boolean allData) {
7812 final boolean mounted;
7813 if (Environment.isExternalStorageEmulated()) {
7814 mounted = true;
7815 } else {
7816 final String status = Environment.getExternalStorageState();
7817
7818 mounted = status.equals(Environment.MEDIA_MOUNTED)
7819 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
7820 }
7821
7822 if (!mounted) {
7823 return;
7824 }
7825
7826 final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
7827 ClearStorageConnection conn = new ClearStorageConnection();
7828 if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE)) {
7829 try {
7830 long timeout = SystemClock.uptimeMillis() + 5000;
7831 synchronized (conn) {
7832 long now = SystemClock.uptimeMillis();
7833 while (conn.mContainerService == null && now < timeout) {
7834 try {
7835 conn.wait(timeout - now);
7836 } catch (InterruptedException e) {
7837 }
7838 }
7839 }
7840 if (conn.mContainerService == null) {
7841 return;
7842 }
7843 final File externalCacheDir = Environment
7844 .getExternalStorageAppCacheDirectory(packageName);
7845 try {
7846 conn.mContainerService.clearDirectory(externalCacheDir.toString());
7847 } catch (RemoteException e) {
7848 }
7849 if (allData) {
7850 final File externalDataDir = Environment
7851 .getExternalStorageAppDataDirectory(packageName);
7852 try {
7853 conn.mContainerService.clearDirectory(externalDataDir.toString());
7854 } catch (RemoteException e) {
7855 }
7856 final File externalMediaDir = Environment
7857 .getExternalStorageAppMediaDirectory(packageName);
7858 try {
7859 conn.mContainerService.clearDirectory(externalMediaDir.toString());
7860 } catch (RemoteException e) {
7861 }
7862 }
7863 } finally {
7864 mContext.unbindService(conn);
7865 }
7866 }
7867 }
7868
Amith Yamasani483f3b02012-03-13 16:08:00 -07007869 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007870 public void clearApplicationUserData(final String packageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07007871 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 mContext.enforceCallingOrSelfPermission(
7873 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
Amith Yamasani483f3b02012-03-13 16:08:00 -07007874 checkValidCaller(Binder.getCallingUid(), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007875 // Queue up an async operation since the package deletion may take a little while.
7876 mHandler.post(new Runnable() {
7877 public void run() {
7878 mHandler.removeCallbacks(this);
7879 final boolean succeeded;
7880 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07007881 succeeded = clearApplicationUserDataLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 }
Dianne Hackborn183ce022012-06-29 15:00:21 -07007883 clearExternalStorageDataSync(packageName, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 if (succeeded) {
7885 // invoke DeviceStorageMonitor's update method to clear any notifications
7886 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
7887 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
7888 if (dsm != null) {
7889 dsm.updateMemory();
7890 }
7891 }
7892 if(observer != null) {
7893 try {
7894 observer.onRemoveCompleted(packageName, succeeded);
7895 } catch (RemoteException e) {
7896 Log.i(TAG, "Observer no longer exists.");
7897 }
7898 } //end if observer
7899 } //end run
7900 });
7901 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007902
Amith Yamasani483f3b02012-03-13 16:08:00 -07007903 private boolean clearApplicationUserDataLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007905 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 return false;
7907 }
7908 PackageParser.Package p;
7909 boolean dataOnly = false;
7910 synchronized (mPackages) {
7911 p = mPackages.get(packageName);
7912 if(p == null) {
7913 dataOnly = true;
7914 PackageSetting ps = mSettings.mPackages.get(packageName);
7915 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007916 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 return false;
7918 }
7919 p = ps.pkg;
7920 }
7921 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08007922
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08007923 if (!dataOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 //need to check this only for fully installed applications
7925 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007926 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 return false;
7928 }
7929 final ApplicationInfo applicationInfo = p.applicationInfo;
7930 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007931 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 return false;
7933 }
7934 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007935 int retCode = mInstaller.clearUserData(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007936 if (retCode < 0) {
7937 Slog.w(TAG, "Couldn't remove cache files for package: "
7938 + packageName);
7939 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 }
7941 return true;
7942 }
7943
7944 public void deleteApplicationCacheFiles(final String packageName,
7945 final IPackageDataObserver observer) {
7946 mContext.enforceCallingOrSelfPermission(
7947 android.Manifest.permission.DELETE_CACHE_FILES, null);
7948 // Queue up an async operation since the package deletion may take a little while.
Amith Yamasani483f3b02012-03-13 16:08:00 -07007949 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950 mHandler.post(new Runnable() {
7951 public void run() {
7952 mHandler.removeCallbacks(this);
7953 final boolean succeded;
7954 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07007955 succeded = deleteApplicationCacheFilesLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956 }
Dianne Hackborn183ce022012-06-29 15:00:21 -07007957 clearExternalStorageDataSync(packageName, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958 if(observer != null) {
7959 try {
7960 observer.onRemoveCompleted(packageName, succeded);
7961 } catch (RemoteException e) {
7962 Log.i(TAG, "Observer no longer exists.");
7963 }
7964 } //end if observer
7965 } //end run
7966 });
7967 }
7968
Amith Yamasani483f3b02012-03-13 16:08:00 -07007969 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007971 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007972 return false;
7973 }
7974 PackageParser.Package p;
7975 synchronized (mPackages) {
7976 p = mPackages.get(packageName);
7977 }
7978 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007979 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 return false;
7981 }
7982 final ApplicationInfo applicationInfo = p.applicationInfo;
7983 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007984 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007985 return false;
7986 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007987 // TODO: Pass userId to deleteCacheFiles
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007988 int retCode = mInstaller.deleteCacheFiles(packageName);
7989 if (retCode < 0) {
7990 Slog.w(TAG, "Couldn't remove cache files for package: "
7991 + packageName);
7992 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007993 }
7994 return true;
7995 }
7996
7997 public void getPackageSizeInfo(final String packageName,
7998 final IPackageStatsObserver observer) {
7999 mContext.enforceCallingOrSelfPermission(
8000 android.Manifest.permission.GET_PACKAGE_SIZE, null);
Kenny Root366949c2011-01-14 17:18:14 -08008001
Kenny Roota69b7eb2012-05-14 14:47:06 -07008002 PackageStats stats = new PackageStats(packageName);
Kenny Root366949c2011-01-14 17:18:14 -08008003
Kenny Roota69b7eb2012-05-14 14:47:06 -07008004 /*
8005 * Queue up an async operation since the package measurement may take a
8006 * little while.
8007 */
8008 Message msg = mHandler.obtainMessage(INIT_COPY);
8009 msg.obj = new MeasureParams(stats, observer);
8010 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 }
8012
8013 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
8014 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008015 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 return false;
8017 }
8018 PackageParser.Package p;
8019 boolean dataOnly = false;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008020 String asecPath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 synchronized (mPackages) {
8022 p = mPackages.get(packageName);
8023 if(p == null) {
8024 dataOnly = true;
8025 PackageSetting ps = mSettings.mPackages.get(packageName);
8026 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008027 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 return false;
8029 }
8030 p = ps.pkg;
8031 }
Kenny Root2afded12012-06-04 16:39:47 -07008032 if (p != null && (isExternal(p) || isForwardLocked(p))) {
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008033 String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
8034 if (secureContainerId != null) {
8035 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
8036 }
8037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 }
8039 String publicSrcDir = null;
8040 if(!dataOnly) {
8041 final ApplicationInfo applicationInfo = p.applicationInfo;
8042 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008043 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 return false;
8045 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07008046 if (isForwardLocked(p)) {
8047 publicSrcDir = applicationInfo.publicSourceDir;
8048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008049 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07008050 int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
8051 asecPath, pStats);
8052 if (res < 0) {
8053 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 }
Kenny Root2afded12012-06-04 16:39:47 -07008055
8056 // Fix-up for forward-locked applications in ASEC containers.
8057 if (!isExternal(p)) {
8058 pStats.codeSize += pStats.externalCodeSize;
8059 pStats.externalCodeSize = 0L;
8060 }
8061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008062 return true;
8063 }
8064
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07008067 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 }
8069
8070 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07008071 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 }
8073
8074 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08008075 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 }
8077
Kenny Root447106f2011-03-23 11:00:15 -07008078 private int getUidTargetSdkVersionLockedLPr(int uid) {
8079 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008080 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07008081 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008082 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07008083 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008084 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07008085 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008086 if (ps.pkg != null) {
8087 int v = ps.pkg.applicationInfo.targetSdkVersion;
8088 if (v < vers) vers = v;
8089 }
8090 }
8091 return vers;
8092 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07008093 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008094 if (ps.pkg != null) {
8095 return ps.pkg.applicationInfo.targetSdkVersion;
8096 }
8097 }
8098 return Build.VERSION_CODES.CUR_DEVELOPMENT;
8099 }
8100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 public void addPreferredActivity(IntentFilter filter, int match,
8102 ComponentName[] set, ComponentName activity) {
Kenny Root447106f2011-03-23 11:00:15 -07008103 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008105 if (mContext.checkCallingOrSelfPermission(
8106 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8107 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008108 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008109 < Build.VERSION_CODES.FROYO) {
8110 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
8111 + Binder.getCallingUid());
8112 return;
8113 }
8114 mContext.enforceCallingOrSelfPermission(
8115 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8116 }
8117
8118 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
8120 mSettings.mPreferredActivities.addFilter(
8121 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008122 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 }
8124 }
8125
Satish Sampath8dbe6122009-06-02 23:35:54 +01008126 public void replacePreferredActivity(IntentFilter filter, int match,
8127 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01008128 if (filter.countActions() != 1) {
8129 throw new IllegalArgumentException(
8130 "replacePreferredActivity expects filter to have only 1 action.");
8131 }
8132 if (filter.countCategories() != 1) {
8133 throw new IllegalArgumentException(
8134 "replacePreferredActivity expects filter to have only 1 category.");
8135 }
8136 if (filter.countDataAuthorities() != 0
8137 || filter.countDataPaths() != 0
8138 || filter.countDataSchemes() != 0
8139 || filter.countDataTypes() != 0) {
8140 throw new IllegalArgumentException(
8141 "replacePreferredActivity expects filter to have no data authorities, " +
8142 "paths, schemes or types.");
8143 }
8144 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008145 if (mContext.checkCallingOrSelfPermission(
8146 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8147 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008148 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008149 < Build.VERSION_CODES.FROYO) {
8150 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
8151 + Binder.getCallingUid());
8152 return;
8153 }
8154 mContext.enforceCallingOrSelfPermission(
8155 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8156 }
8157
Dianne Hackborn04505102012-02-29 12:34:04 -08008158 ArrayList<PreferredActivity> removed = null;
Satish Sampath8dbe6122009-06-02 23:35:54 +01008159 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
8160 String action = filter.getAction(0);
8161 String category = filter.getCategory(0);
8162 while (it.hasNext()) {
8163 PreferredActivity pa = it.next();
8164 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008165 if (removed == null) {
8166 removed = new ArrayList<PreferredActivity>();
8167 }
8168 removed.add(pa);
8169 Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
Satish Sampath8dbe6122009-06-02 23:35:54 +01008170 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
8171 }
8172 }
Dianne Hackborn04505102012-02-29 12:34:04 -08008173 if (removed != null) {
8174 for (int i=0; i<removed.size(); i++) {
8175 PreferredActivity pa = removed.get(i);
8176 mSettings.mPreferredActivities.removeFilter(pa);
8177 }
8178 }
Satish Sampath8dbe6122009-06-02 23:35:54 +01008179 addPreferredActivity(filter, match, set, activity);
8180 }
8181 }
8182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07008184 final int uid = Binder.getCallingUid();
8185 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08008187 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008188 if (pkg == null || pkg.applicationInfo.uid != uid) {
8189 if (mContext.checkCallingOrSelfPermission(
8190 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8191 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008192 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008193 < Build.VERSION_CODES.FROYO) {
8194 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
8195 + Binder.getCallingUid());
8196 return;
8197 }
8198 mContext.enforceCallingOrSelfPermission(
8199 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8200 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08008201 }
8202
Kenny Root447106f2011-03-23 11:00:15 -07008203 if (clearPackagePreferredActivitiesLPw(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008204 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205 }
8206 }
8207 }
8208
Kenny Root447106f2011-03-23 11:00:15 -07008209 boolean clearPackagePreferredActivitiesLPw(String packageName) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008210 ArrayList<PreferredActivity> removed = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008211 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
8212 while (it.hasNext()) {
8213 PreferredActivity pa = it.next();
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08008214 if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008215 if (removed == null) {
8216 removed = new ArrayList<PreferredActivity>();
8217 }
8218 removed.add(pa);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 }
8220 }
Dianne Hackborn04505102012-02-29 12:34:04 -08008221 if (removed != null) {
8222 for (int i=0; i<removed.size(); i++) {
8223 PreferredActivity pa = removed.get(i);
8224 mSettings.mPreferredActivities.removeFilter(pa);
8225 }
8226 return true;
8227 }
8228 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 }
8230
8231 public int getPreferredActivities(List<IntentFilter> outFilters,
8232 List<ComponentName> outActivities, String packageName) {
8233
8234 int num = 0;
Kenny Root447106f2011-03-23 11:00:15 -07008235 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008237 final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008238 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07008239 final PreferredActivity pa = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 if (packageName == null
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08008241 || pa.mPref.mComponent.getPackageName().equals(packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008242 if (outFilters != null) {
8243 outFilters.add(new IntentFilter(pa));
8244 }
8245 if (outActivities != null) {
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08008246 outActivities.add(pa.mPref.mComponent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 }
8248 }
8249 }
8250 }
8251
8252 return num;
8253 }
8254
Amith Yamasani483f3b02012-03-13 16:08:00 -07008255 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 public void setApplicationEnabledSetting(String appPackageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008257 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008258 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008259 setEnabledSetting(appPackageName, null, newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 }
8261
Amith Yamasani483f3b02012-03-13 16:08:00 -07008262 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 public void setComponentEnabledSetting(ComponentName componentName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008264 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008265 if (!sUserManager.exists(userId)) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 setEnabledSetting(componentName.getPackageName(),
Amith Yamasani483f3b02012-03-13 16:08:00 -07008267 componentName.getClassName(), newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 }
8269
8270 private void setEnabledSetting(
Amith Yamasani483f3b02012-03-13 16:08:00 -07008271 final String packageName, String className, int newState, final int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
8273 || newState == COMPONENT_ENABLED_STATE_ENABLED
Dianne Hackborn0ac30312011-06-17 14:49:23 -07008274 || newState == COMPONENT_ENABLED_STATE_DISABLED
8275 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008276 throw new IllegalArgumentException("Invalid new component state: "
8277 + newState);
8278 }
8279 PackageSetting pkgSetting;
8280 final int uid = Binder.getCallingUid();
8281 final int permission = mContext.checkCallingPermission(
8282 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
Amith Yamasani483f3b02012-03-13 16:08:00 -07008283 checkValidCaller(uid, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008285 boolean sendNow = false;
8286 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008287 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008288 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008289 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -07008290
8291 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008293 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008295 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008296 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008297 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 }
8299 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008300 "Unknown component: " + packageName
8301 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008302 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008303 // Allow root and verify that userId is not being specified by a different user
Amith Yamasani13593602012-03-22 16:16:17 -07008304 if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.appId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008305 throw new SecurityException(
8306 "Permission Denial: attempt to change component state from pid="
8307 + Binder.getCallingPid()
Amith Yamasani13593602012-03-22 16:16:17 -07008308 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008310 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 // We're dealing with an application/package level state change
Amith Yamasani483f3b02012-03-13 16:08:00 -07008312 if (pkgSetting.getEnabled(userId) == newState) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008313 // Nothing to do
8314 return;
8315 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008316 pkgSetting.setEnabled(newState, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07008317 // pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 } else {
8319 // We're dealing with a component level state change
Dianne Hackborn65696252012-03-05 18:49:21 -08008320 // First, verify that this is a valid class name.
8321 PackageParser.Package pkg = pkgSetting.pkg;
8322 if (pkg == null || !pkg.hasComponentClassName(className)) {
8323 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
8324 throw new IllegalArgumentException("Component class " + className
8325 + " does not exist in " + packageName);
8326 } else {
8327 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
8328 + className + " does not exist in " + packageName);
8329 }
8330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008331 switch (newState) {
8332 case COMPONENT_ENABLED_STATE_ENABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07008333 if (!pkgSetting.enableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008334 return;
8335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 break;
8337 case COMPONENT_ENABLED_STATE_DISABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07008338 if (!pkgSetting.disableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008339 return;
8340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 break;
8342 case COMPONENT_ENABLED_STATE_DEFAULT:
Amith Yamasani483f3b02012-03-13 16:08:00 -07008343 if (!pkgSetting.restoreComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008344 return;
8345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 break;
8347 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008348 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008349 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 }
8351 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008352 mSettings.writePackageRestrictionsLPr(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07008353 packageUid = UserId.getUid(userId, pkgSetting.appId);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008354 components = mPendingBroadcasts.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07008355 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008356 if (newPackage) {
8357 components = new ArrayList<String>();
8358 }
8359 if (!components.contains(componentName)) {
8360 components.add(componentName);
8361 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008362 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
8363 sendNow = true;
8364 // Purge entry from pending broadcast list if another one exists already
8365 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008366 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008367 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008368 if (newPackage) {
8369 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008370 }
8371 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
8372 // Schedule a message
8373 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
8374 }
8375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008378 long callingId = Binder.clearCallingIdentity();
8379 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008380 if (sendNow) {
8381 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008382 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 } finally {
8385 Binder.restoreCallingIdentity(callingId);
8386 }
8387 }
8388
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008389 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008390 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08008391 if (DEBUG_INSTALL)
8392 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
8393 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008394 Bundle extras = new Bundle(4);
8395 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
8396 String nameList[] = new String[componentNames.size()];
8397 componentNames.toArray(nameList);
8398 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008399 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
8400 extras.putInt(Intent.EXTRA_UID, packageUid);
Amith Yamasani13593602012-03-22 16:16:17 -07008401 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
8402 UserId.getUserId(packageUid));
Dianne Hackborne7f97212011-02-24 14:40:20 -08008403 }
8404
Amith Yamasani483f3b02012-03-13 16:08:00 -07008405 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008406 if (!sUserManager.exists(userId)) return;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008407 final int uid = Binder.getCallingUid();
8408 final int permission = mContext.checkCallingOrSelfPermission(
8409 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
8410 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Amith Yamasani483f3b02012-03-13 16:08:00 -07008411 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008412 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -08008413 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008414 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008415 uid, userId)) {
8416 scheduleWritePackageRestrictionsLocked(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08008417 }
8418 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008419 }
8420
Jacek Surazski65e13172009-04-28 15:26:38 +02008421 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07008422 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +02008423 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008424 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02008425 }
8426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008427
Amith Yamasani483f3b02012-03-13 16:08:00 -07008428 @Override
8429 public int getApplicationEnabledSetting(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008430 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008431 int uid = Binder.getCallingUid();
8432 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008433 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008434 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008435 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 }
8437 }
8438
Amith Yamasani483f3b02012-03-13 16:08:00 -07008439 @Override
8440 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008441 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008442 int uid = Binder.getCallingUid();
8443 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008444 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008446 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 }
8448 }
8449
8450 public void enterSafeMode() {
Kenny Root461ff1f2011-08-09 09:43:03 -07008451 enforceSystemOrRoot("Only the system can request entering safe mode");
8452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 if (!mSystemReady) {
8454 mSafeMode = true;
8455 }
8456 }
8457
8458 public void systemReady() {
8459 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008460
8461 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008462 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008463 mContext.getContentResolver(),
8464 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008465 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008466 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008467 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 }
8470
8471 public boolean isSafeMode() {
8472 return mSafeMode;
8473 }
8474
8475 public boolean hasSystemUidErrors() {
8476 return mHasSystemUidErrors;
8477 }
8478
8479 static String arrayToString(int[] array) {
8480 StringBuffer buf = new StringBuffer(128);
8481 buf.append('[');
8482 if (array != null) {
8483 for (int i=0; i<array.length; i++) {
8484 if (i > 0) buf.append(", ");
8485 buf.append(array[i]);
8486 }
8487 }
8488 buf.append(']');
8489 return buf.toString();
8490 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008491
Kenny Root447106f2011-03-23 11:00:15 -07008492 static class DumpState {
8493 public static final int DUMP_LIBS = 1 << 0;
8494
8495 public static final int DUMP_FEATURES = 1 << 1;
8496
8497 public static final int DUMP_RESOLVERS = 1 << 2;
8498
8499 public static final int DUMP_PERMISSIONS = 1 << 3;
8500
8501 public static final int DUMP_PACKAGES = 1 << 4;
8502
8503 public static final int DUMP_SHARED_USERS = 1 << 5;
8504
8505 public static final int DUMP_MESSAGES = 1 << 6;
8506
8507 public static final int DUMP_PROVIDERS = 1 << 7;
8508
Kenny Root05ca4c92011-09-15 10:36:25 -07008509 public static final int DUMP_VERIFIERS = 1 << 8;
8510
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07008511 public static final int DUMP_PREFERRED = 1 << 9;
8512
8513 public static final int DUMP_PREFERRED_XML = 1 << 10;
8514
Kenny Root447106f2011-03-23 11:00:15 -07008515 public static final int OPTION_SHOW_FILTERS = 1 << 0;
8516
8517 private int mTypes;
8518
8519 private int mOptions;
8520
8521 private boolean mTitlePrinted;
8522
8523 private SharedUserSetting mSharedUser;
8524
8525 public boolean isDumping(int type) {
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07008526 if (mTypes == 0 && type != DUMP_PREFERRED_XML) {
Kenny Root447106f2011-03-23 11:00:15 -07008527 return true;
8528 }
8529
8530 return (mTypes & type) != 0;
8531 }
8532
8533 public void setDump(int type) {
8534 mTypes |= type;
8535 }
8536
8537 public boolean isOptionEnabled(int option) {
8538 return (mOptions & option) != 0;
8539 }
8540
8541 public void setOptionEnabled(int option) {
8542 mOptions |= option;
8543 }
8544
8545 public boolean onTitlePrinted() {
8546 final boolean printed = mTitlePrinted;
8547 mTitlePrinted = true;
8548 return printed;
8549 }
8550
8551 public boolean getTitlePrinted() {
8552 return mTitlePrinted;
8553 }
8554
8555 public void setTitlePrinted(boolean enabled) {
8556 mTitlePrinted = enabled;
8557 }
8558
8559 public SharedUserSetting getSharedUser() {
8560 return mSharedUser;
8561 }
8562
8563 public void setSharedUser(SharedUserSetting user) {
8564 mSharedUser = user;
8565 }
8566 }
8567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 @Override
8569 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
8570 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
8571 != PackageManager.PERMISSION_GRANTED) {
8572 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8573 + Binder.getCallingPid()
8574 + ", uid=" + Binder.getCallingUid()
8575 + " without permission "
8576 + android.Manifest.permission.DUMP);
8577 return;
8578 }
8579
Kenny Root447106f2011-03-23 11:00:15 -07008580 DumpState dumpState = new DumpState();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008581
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008582 String packageName = null;
8583
8584 int opti = 0;
8585 while (opti < args.length) {
8586 String opt = args[opti];
8587 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
8588 break;
8589 }
8590 opti++;
8591 if ("-a".equals(opt)) {
8592 // Right now we only know how to print all.
8593 } else if ("-h".equals(opt)) {
8594 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008595 pw.println(" [-h] [-f] [cmd] ...");
8596 pw.println(" -f: print details of intent filters");
8597 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008598 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008599 pw.println(" l[ibraries]: list known shared libraries");
8600 pw.println(" f[ibraries]: list device features");
8601 pw.println(" r[esolvers]: dump intent resolvers");
8602 pw.println(" perm[issions]: dump permissions");
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07008603 pw.println(" pref[erred]: print preferred package settings");
8604 pw.println(" preferred-xml: print preferred package settings as xml");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008605 pw.println(" prov[iders]: dump content providers");
8606 pw.println(" p[ackages]: dump installed packages");
8607 pw.println(" s[hared-users]: dump shared user IDs");
8608 pw.println(" m[essages]: print collected runtime messages");
Kenny Root05ca4c92011-09-15 10:36:25 -07008609 pw.println(" v[erifiers]: print package verifier info");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008610 pw.println(" <package.name>: info about given package");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008611 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008612 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -07008613 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008614 } else {
8615 pw.println("Unknown argument: " + opt + "; use -h for help");
8616 }
8617 }
8618
8619 // Is the caller requesting to dump a particular piece of data?
8620 if (opti < args.length) {
8621 String cmd = args[opti];
8622 opti++;
8623 // Is this a package name?
8624 if ("android".equals(cmd) || cmd.contains(".")) {
8625 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008626 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008627 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008628 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008629 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008630 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008631 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008632 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008633 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07008634 } else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
8635 dumpState.setDump(DumpState.DUMP_PREFERRED);
8636 } else if ("preferred-xml".equals(cmd)) {
8637 dumpState.setDump(DumpState.DUMP_PREFERRED_XML);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008638 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008639 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008640 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008641 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008642 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008643 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008644 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008645 dumpState.setDump(DumpState.DUMP_MESSAGES);
Kenny Root05ca4c92011-09-15 10:36:25 -07008646 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
8647 dumpState.setDump(DumpState.DUMP_VERIFIERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008648 }
8649 }
Kenny Root447106f2011-03-23 11:00:15 -07008650
8651 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 synchronized (mPackages) {
Kenny Root05ca4c92011-09-15 10:36:25 -07008653 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
8654 if (dumpState.onTitlePrinted())
8655 pw.println(" ");
8656 pw.println("Verifiers:");
8657 pw.print(" Required: ");
8658 pw.print(mRequiredVerifierPackage);
8659 pw.print(" (uid=");
Amith Yamasani483f3b02012-03-13 16:08:00 -07008660 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
Kenny Root05ca4c92011-09-15 10:36:25 -07008661 pw.println(")");
8662 }
8663
Kenny Root447106f2011-03-23 11:00:15 -07008664 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
8665 if (dumpState.onTitlePrinted())
8666 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008667 pw.println("Libraries:");
Kenny Root447106f2011-03-23 11:00:15 -07008668 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008669 while (it.hasNext()) {
8670 String name = it.next();
8671 pw.print(" ");
8672 pw.print(name);
8673 pw.print(" -> ");
8674 pw.println(mSharedLibraries.get(name));
8675 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008676 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008677
Kenny Root447106f2011-03-23 11:00:15 -07008678 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
8679 if (dumpState.onTitlePrinted())
8680 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008681 pw.println("Features:");
8682 Iterator<String> it = mAvailableFeatures.keySet().iterator();
8683 while (it.hasNext()) {
8684 String name = it.next();
8685 pw.print(" ");
8686 pw.println(name);
8687 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008688 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008689
Kenny Root447106f2011-03-23 11:00:15 -07008690 if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
8691 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
8692 : "Activity Resolver Table:", " ", packageName,
8693 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8694 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008695 }
Kenny Root447106f2011-03-23 11:00:15 -07008696 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
8697 : "Receiver Resolver Table:", " ", packageName,
8698 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8699 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008700 }
Kenny Root447106f2011-03-23 11:00:15 -07008701 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
8702 : "Service Resolver Table:", " ", packageName,
8703 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8704 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008705 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07008706 }
8707
8708 if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
Kenny Root447106f2011-03-23 11:00:15 -07008709 if (mSettings.mPreferredActivities.dump(pw,
8710 dumpState.getTitlePrinted() ? "\nPreferred Activities:"
8711 : "Preferred Activities:", " ",
8712 packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8713 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008714 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008715 }
Dianne Hackbornfc8b7fe2012-06-18 15:38:12 -07008716
8717 if (dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)) {
8718 pw.flush();
8719 FileOutputStream fout = new FileOutputStream(fd);
8720 BufferedOutputStream str = new BufferedOutputStream(fout);
8721 XmlSerializer serializer = new FastXmlSerializer();
8722 try {
8723 serializer.setOutput(str, "utf-8");
8724 serializer.startDocument(null, true);
8725 serializer.setFeature(
8726 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
8727 mSettings.writePreferredActivitiesLPr(serializer);
8728 serializer.endDocument();
8729 serializer.flush();
8730 } catch (IllegalArgumentException e) {
8731 pw.println("Failed writing: " + e);
8732 } catch (IllegalStateException e) {
8733 pw.println("Failed writing: " + e);
8734 } catch (IOException e) {
8735 pw.println("Failed writing: " + e);
8736 }
8737 }
8738
Kenny Root447106f2011-03-23 11:00:15 -07008739 if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
8740 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008741 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008742
Kenny Root447106f2011-03-23 11:00:15 -07008743 if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
8744 boolean printedSomething = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008745 for (PackageParser.Provider p : mProvidersByComponent.values()) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008746 if (packageName != null && !packageName.equals(p.info.packageName)) {
8747 continue;
8748 }
8749 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -07008750 if (dumpState.onTitlePrinted())
8751 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008752 pw.println("Registered ContentProviders:");
8753 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008754 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008755 pw.print(" "); pw.print(p.getComponentShortName()); pw.println(":");
8756 pw.print(" "); pw.println(p.toString());
8757 }
8758 printedSomething = false;
8759 for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) {
8760 PackageParser.Provider p = entry.getValue();
8761 if (packageName != null && !packageName.equals(p.info.packageName)) {
8762 continue;
8763 }
8764 if (!printedSomething) {
8765 if (dumpState.onTitlePrinted())
8766 pw.println(" ");
8767 pw.println("ContentProvider Authorities:");
8768 printedSomething = true;
8769 }
8770 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
8771 pw.print(" "); pw.println(p.toString());
Kenny Rooteca64b32012-06-25 16:37:32 -07008772 if (p.info != null && p.info.applicationInfo != null) {
8773 final String appInfo = p.info.applicationInfo.toString();
8774 pw.print(" applicationInfo="); pw.println(appInfo);
8775 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008776 }
8777 }
8778
Kenny Root447106f2011-03-23 11:00:15 -07008779 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
8780 mSettings.dumpPackagesLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008781 }
Kenny Root447106f2011-03-23 11:00:15 -07008782
8783 if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
8784 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008785 }
Kenny Root447106f2011-03-23 11:00:15 -07008786
8787 if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
8788 if (dumpState.onTitlePrinted())
8789 pw.println(" ");
8790 mSettings.dumpReadMessagesLPr(pw, dumpState);
8791
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008792 pw.println(" ");
8793 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -07008794 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008795 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008796 try {
8797 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -07008798 final int avail = in.available();
8799 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008800 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008801 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008802 } catch (FileNotFoundException e) {
8803 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008804 } finally {
8805 if (in != null) {
8806 try {
8807 in.close();
Kenny Root447106f2011-03-23 11:00:15 -07008808 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008809 }
8810 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008811 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 }
8814 }
8815
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008816 // ------- apps on sdcard specific code -------
8817 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -07008818
Kenny Root305bcbf2010-09-03 07:56:38 -07008819 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -07008820
Kenny Root305bcbf2010-09-03 07:56:38 -07008821 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -07008822
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008823 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008824
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008825 private String getEncryptKey() {
8826 try {
Kenny Root305bcbf2010-09-03 07:56:38 -07008827 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
8828 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008829 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -07008830 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
8831 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008832 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008833 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008834 return null;
8835 }
8836 }
8837 return sdEncKey;
8838 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008839 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008840 return null;
Rich Cannings8d578832010-09-09 15:12:40 -07008841 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -07008842 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -07008843 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008844 }
Rich Cannings8d578832010-09-09 15:12:40 -07008845
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008846 }
8847
Kenny Root447106f2011-03-23 11:00:15 -07008848 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -07008849 int tmpIdx = 1;
8850 String list[] = PackageHelper.getSecureContainerList();
8851 if (list != null) {
8852 for (final String name : list) {
8853 // Ignore null and non-temporary container entries
8854 if (name == null || !name.startsWith(mTempContainerPrefix)) {
8855 continue;
8856 }
8857
8858 String subStr = name.substring(mTempContainerPrefix.length());
8859 try {
8860 int cid = Integer.parseInt(subStr);
8861 if (cid >= tmpIdx) {
8862 tmpIdx = cid + 1;
8863 }
8864 } catch (NumberFormatException e) {
8865 }
8866 }
8867 }
8868 return mTempContainerPrefix + tmpIdx;
8869 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008870
Kenny Root447106f2011-03-23 11:00:15 -07008871 /*
8872 * Update media status on PackageManager.
8873 */
8874 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
8875 int callingUid = Binder.getCallingUid();
8876 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
8877 throw new SecurityException("Media status can only be updated by the system");
8878 }
8879 // reader; this apparently protects mMediaMounted, but should probably
8880 // be a different lock in that case.
8881 synchronized (mPackages) {
8882 Log.i(TAG, "Updating external media status from "
8883 + (mMediaMounted ? "mounted" : "unmounted") + " to "
8884 + (mediaStatus ? "mounted" : "unmounted"));
8885 if (DEBUG_SD_INSTALL)
8886 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
8887 + ", mMediaMounted=" + mMediaMounted);
8888 if (mediaStatus == mMediaMounted) {
8889 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
8890 : 0, -1);
8891 mHandler.sendMessage(msg);
8892 return;
8893 }
8894 mMediaMounted = mediaStatus;
8895 }
8896 // Queue up an async operation since the package installation may take a
8897 // little while.
8898 mHandler.post(new Runnable() {
8899 public void run() {
Kenny Root447106f2011-03-23 11:00:15 -07008900 updateExternalMediaStatusInner(mediaStatus, reportStatus);
8901 }
8902 });
8903 }
8904
Kenny Root51a573c2012-05-17 13:30:28 -07008905 /**
8906 * Called by MountService when the initial ASECs to scan are available.
8907 * Should block until all the ASEC containers are finished being scanned.
8908 */
8909 public void scanAvailableAsecs() {
8910 updateExternalMediaStatusInner(true, false);
8911 }
8912
Kenny Root447106f2011-03-23 11:00:15 -07008913 /*
8914 * Collect information of applications on external media, map them against
8915 * existing containers and update information based on current mount status.
8916 * Please note that we always have to report status if reportStatus has been
8917 * set to true especially when unloading packages.
8918 */
Kenny Root6dceb882012-04-12 14:23:49 -07008919 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus) {
Kenny Root447106f2011-03-23 11:00:15 -07008920 // Collection of uids
8921 int uidArr[] = null;
8922 // Collection of stale containers
8923 HashSet<String> removeCids = new HashSet<String>();
8924 // Collection of packages on external media with valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07008925 HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
Kenny Root447106f2011-03-23 11:00:15 -07008926 // Get list of secure containers.
8927 final String list[] = PackageHelper.getSecureContainerList();
8928 if (list == null || list.length == 0) {
8929 Log.i(TAG, "No secure containers on sdcard");
8930 } else {
8931 // Process list of secure containers and categorize them
8932 // as active or stale based on their package internal state.
8933 int uidList[] = new int[list.length];
8934 int num = 0;
8935 // reader
8936 synchronized (mPackages) {
8937 for (String cid : list) {
Kenny Root447106f2011-03-23 11:00:15 -07008938 if (DEBUG_SD_INSTALL)
8939 Log.i(TAG, "Processing container " + cid);
Kenny Rootc7a89992012-06-05 15:13:17 -07008940 String pkgName = getAsecPackageName(cid);
Kenny Root447106f2011-03-23 11:00:15 -07008941 if (pkgName == null) {
8942 if (DEBUG_SD_INSTALL)
8943 Log.i(TAG, "Container : " + cid + " stale");
8944 removeCids.add(cid);
8945 continue;
8946 }
8947 if (DEBUG_SD_INSTALL)
8948 Log.i(TAG, "Looking for pkg : " + pkgName);
Kenny Rootc7a89992012-06-05 15:13:17 -07008949
8950 final PackageSetting ps = mSettings.mPackages.get(pkgName);
8951 if (ps == null) {
8952 Log.i(TAG, "Deleting container with no matching settings " + cid);
8953 removeCids.add(cid);
8954 continue;
8955 }
8956
8957 final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
Kenny Root447106f2011-03-23 11:00:15 -07008958 // The package status is changed only if the code path
8959 // matches between settings and the container id.
Kenny Rootc7a89992012-06-05 15:13:17 -07008960 if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
8961 if (DEBUG_SD_INSTALL) {
Kenny Root447106f2011-03-23 11:00:15 -07008962 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
8963 + " at code path: " + ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -07008964 }
8965
Kenny Root447106f2011-03-23 11:00:15 -07008966 // We do have a valid package installed on sdcard
8967 processCids.put(args, ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -07008968 final int uid = ps.appId;
Kenny Root447106f2011-03-23 11:00:15 -07008969 if (uid != -1) {
8970 uidList[num++] = uid;
8971 }
8972 } else {
Kenny Rootc7a89992012-06-05 15:13:17 -07008973 Log.i(TAG, "Deleting stale container for " + cid);
Kenny Root447106f2011-03-23 11:00:15 -07008974 removeCids.add(cid);
8975 }
8976 }
8977 }
8978
8979 if (num > 0) {
8980 // Sort uid list
8981 Arrays.sort(uidList, 0, num);
8982 // Throw away duplicates
8983 uidArr = new int[num];
8984 uidArr[0] = uidList[0];
8985 int di = 0;
8986 for (int i = 1; i < num; i++) {
8987 if (uidList[i - 1] != uidList[i]) {
8988 uidArr[di++] = uidList[i];
8989 }
8990 }
8991 }
8992 }
8993 // Process packages with valid entries.
Kenny Root6dceb882012-04-12 14:23:49 -07008994 if (isMounted) {
Kenny Root447106f2011-03-23 11:00:15 -07008995 if (DEBUG_SD_INSTALL)
8996 Log.i(TAG, "Loading packages");
8997 loadMediaPackages(processCids, uidArr, removeCids);
8998 startCleaningPackages();
8999 } else {
9000 if (DEBUG_SD_INSTALL)
9001 Log.i(TAG, "Unloading packages");
9002 unloadMediaPackages(processCids, uidArr, reportStatus);
9003 }
9004 }
9005
9006 private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList,
9007 int uidArr[], IIntentReceiver finishedReceiver) {
9008 int size = pkgList.size();
9009 if (size > 0) {
9010 // Send broadcasts here
9011 Bundle extras = new Bundle();
9012 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
9013 .toArray(new String[size]));
9014 if (uidArr != null) {
9015 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
9016 }
9017 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
9018 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Amith Yamasani13593602012-03-22 16:16:17 -07009019 sendPackageBroadcast(action, null, extras, null, finishedReceiver, UserId.USER_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07009020 }
9021 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009022
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009023 /*
Kenny Root447106f2011-03-23 11:00:15 -07009024 * Look at potentially valid container ids from processCids If package
9025 * information doesn't match the one on record or package scanning fails,
9026 * the cid is added to list of removeCids. We currently don't delete stale
9027 * containers.
9028 */
Kenny Root6dceb882012-04-12 14:23:49 -07009029 private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07009030 HashSet<String> removeCids) {
9031 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07009032 Set<AsecInstallArgs> keys = processCids.keySet();
Kenny Root447106f2011-03-23 11:00:15 -07009033 boolean doGc = false;
Kenny Root6dceb882012-04-12 14:23:49 -07009034 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07009035 String codePath = processCids.get(args);
9036 if (DEBUG_SD_INSTALL)
9037 Log.i(TAG, "Loading container : " + args.cid);
9038 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9039 try {
9040 // Make sure there are no container errors first.
9041 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
9042 Slog.e(TAG, "Failed to mount cid : " + args.cid
9043 + " when installing from sdcard");
9044 continue;
9045 }
9046 // Check code path here.
9047 if (codePath == null || !codePath.equals(args.getCodePath())) {
9048 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
9049 + " does not match one in settings " + codePath);
9050 continue;
9051 }
9052 // Parse package
Kenny Root51a573c2012-05-17 13:30:28 -07009053 int parseFlags = mDefParseFlags;
9054 if (args.isExternal()) {
9055 parseFlags |= PackageParser.PARSE_ON_SDCARD;
9056 }
Kenny Rootc7a89992012-06-05 15:13:17 -07009057 if (args.isFwdLocked()) {
9058 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
9059 }
Kenny Root51a573c2012-05-17 13:30:28 -07009060
Kenny Root447106f2011-03-23 11:00:15 -07009061 doGc = true;
9062 synchronized (mInstallLock) {
9063 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
9064 0, 0);
9065 // Scan the package
9066 if (pkg != null) {
9067 /*
9068 * TODO why is the lock being held? doPostInstall is
9069 * called in other places without the lock. This needs
9070 * to be straightened out.
9071 */
9072 // writer
9073 synchronized (mPackages) {
9074 retCode = PackageManager.INSTALL_SUCCEEDED;
9075 pkgList.add(pkg.packageName);
9076 // Post process args
Kenny Root6dceb882012-04-12 14:23:49 -07009077 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
9078 pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07009079 }
9080 } else {
9081 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
9082 }
9083 }
9084
9085 } finally {
9086 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
9087 // Don't destroy container here. Wait till gc clears things
9088 // up.
9089 removeCids.add(args.cid);
9090 }
9091 }
9092 }
9093 // writer
9094 synchronized (mPackages) {
9095 // If the platform SDK has changed since the last time we booted,
9096 // we need to re-grant app permission to catch any new ones that
9097 // appear. This is really a hack, and means that apps can in some
9098 // cases get permissions that the user didn't initially explicitly
9099 // allow... it would be nice to have some better way to handle
9100 // this situation.
9101 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
9102 if (regrantPermissions)
9103 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
9104 + mSdkVersion + "; regranting permissions for external storage");
9105 mSettings.mExternalSdkPlatform = mSdkVersion;
9106
9107 // Make sure group IDs have been assigned, and any permission
9108 // changes in other apps are accounted for
Dianne Hackborne639da72012-02-21 15:11:13 -08009109 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
9110 | (regrantPermissions
9111 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
9112 : 0));
Kenny Root447106f2011-03-23 11:00:15 -07009113 // can downgrade to reader
9114 // Persist settings
9115 mSettings.writeLPr();
9116 }
9117 // Send a broadcast to let everyone know we are done processing
9118 if (pkgList.size() > 0) {
9119 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
9120 }
9121 // Force gc to avoid any stale parser references that we might have.
9122 if (doGc) {
9123 Runtime.getRuntime().gc();
9124 }
9125 // List stale containers and destroy stale temporary containers.
9126 if (removeCids != null) {
9127 for (String cid : removeCids) {
9128 if (cid.startsWith(mTempContainerPrefix)) {
9129 Log.i(TAG, "Destroying stale temporary container " + cid);
9130 PackageHelper.destroySdDir(cid);
9131 } else {
9132 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009133 }
9134 }
Kenny Root447106f2011-03-23 11:00:15 -07009135 }
9136 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009137
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009138 /*
Kenny Root447106f2011-03-23 11:00:15 -07009139 * Utility method to unload a list of specified containers
9140 */
Kenny Root6dceb882012-04-12 14:23:49 -07009141 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07009142 // Just unmount all valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07009143 for (AsecInstallArgs arg : cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07009144 synchronized (mInstallLock) {
9145 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009146 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009147 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009148 }
9149
Kenny Root447106f2011-03-23 11:00:15 -07009150 /*
9151 * Unload packages mounted on external media. This involves deleting package
9152 * data from internal structures, sending broadcasts about diabled packages,
9153 * gc'ing to free up references, unmounting all secure containers
9154 * corresponding to packages on external media, and posting a
9155 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
9156 * that we always have to post this message if status has been requested no
9157 * matter what.
9158 */
Kenny Root6dceb882012-04-12 14:23:49 -07009159 private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07009160 final boolean reportStatus) {
9161 if (DEBUG_SD_INSTALL)
9162 Log.i(TAG, "unloading media packages");
9163 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07009164 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
9165 final Set<AsecInstallArgs> keys = processCids.keySet();
9166 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07009167 String pkgName = args.getPackageName();
9168 if (DEBUG_SD_INSTALL)
9169 Log.i(TAG, "Trying to unload pkg : " + pkgName);
9170 // Delete package internally
9171 PackageRemovedInfo outInfo = new PackageRemovedInfo();
9172 synchronized (mInstallLock) {
9173 boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
9174 outInfo, false);
9175 if (res) {
9176 pkgList.add(pkgName);
9177 } else {
9178 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
9179 failedList.add(args);
9180 }
9181 }
9182 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009183
Kenny Root447106f2011-03-23 11:00:15 -07009184 // reader
9185 synchronized (mPackages) {
9186 // We didn't update the settings after removing each package;
9187 // write them now for all packages.
9188 mSettings.writeLPr();
9189 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009190
Kenny Root447106f2011-03-23 11:00:15 -07009191 // We have to absolutely send UPDATED_MEDIA_STATUS only
9192 // after confirming that all the receivers processed the ordered
9193 // broadcast when packages get disabled, force a gc to clean things up.
9194 // and unload all the containers.
9195 if (pkgList.size() > 0) {
9196 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
9197 public void performReceive(Intent intent, int resultCode, String data,
9198 Bundle extras, boolean ordered, boolean sticky) throws RemoteException {
9199 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
9200 reportStatus ? 1 : 0, 1, keys);
9201 mHandler.sendMessage(msg);
9202 }
9203 });
9204 } else {
9205 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
9206 keys);
9207 mHandler.sendMessage(msg);
9208 }
9209 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009210
Kenny Root447106f2011-03-23 11:00:15 -07009211 public void movePackage(final String packageName, final IPackageMoveObserver observer,
9212 final int flags) {
9213 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
9214 int returnCode = PackageManager.MOVE_SUCCEEDED;
9215 int currFlags = 0;
9216 int newFlags = 0;
9217 // reader
9218 synchronized (mPackages) {
9219 PackageParser.Package pkg = mPackages.get(packageName);
9220 if (pkg == null) {
9221 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9222 } else {
9223 // Disable moving fwd locked apps and system packages
9224 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
9225 Slog.w(TAG, "Cannot move system application");
9226 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root447106f2011-03-23 11:00:15 -07009227 } else if (pkg.mOperationPending) {
9228 Slog.w(TAG, "Attempt to move package which has pending operations");
9229 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
9230 } else {
9231 // Find install location first
9232 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
9233 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
9234 Slog.w(TAG, "Ambigous flags specified for move location.");
9235 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9236 } else {
9237 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
9238 : PackageManager.INSTALL_INTERNAL;
9239 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
9240 : PackageManager.INSTALL_INTERNAL;
Kenny Rootbf023582012-05-02 16:56:15 -07009241
Kenny Root447106f2011-03-23 11:00:15 -07009242 if (newFlags == currFlags) {
9243 Slog.w(TAG, "No move required. Trying to move to same location");
9244 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Rootbf023582012-05-02 16:56:15 -07009245 } else {
9246 if (isForwardLocked(pkg)) {
9247 currFlags |= PackageManager.INSTALL_FORWARD_LOCK;
9248 newFlags |= PackageManager.INSTALL_FORWARD_LOCK;
9249 }
Kenny Root447106f2011-03-23 11:00:15 -07009250 }
9251 }
9252 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
9253 pkg.mOperationPending = true;
9254 }
9255 }
9256 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009257
Kenny Root447106f2011-03-23 11:00:15 -07009258 /*
9259 * TODO this next block probably shouldn't be inside the lock. We
9260 * can't guarantee these won't change after this is fired off
9261 * anyway.
9262 */
9263 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Kenny Root6dceb882012-04-12 14:23:49 -07009264 processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1),
9265 returnCode);
Kenny Root447106f2011-03-23 11:00:15 -07009266 } else {
9267 Message msg = mHandler.obtainMessage(INIT_COPY);
9268 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -07009269 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -07009270 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Kenny Root6dceb882012-04-12 14:23:49 -07009271 pkg.applicationInfo.dataDir, pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07009272 msg.obj = mp;
9273 mHandler.sendMessage(msg);
9274 }
9275 }
9276 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009277
Kenny Root447106f2011-03-23 11:00:15 -07009278 private void processPendingMove(final MoveParams mp, final int currentStatus) {
9279 // Queue up an async operation since the package deletion may take a
9280 // little while.
9281 mHandler.post(new Runnable() {
9282 public void run() {
9283 // TODO fix this; this does nothing.
9284 mHandler.removeCallbacks(this);
9285 int returnCode = currentStatus;
9286 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
9287 int uidArr[] = null;
9288 ArrayList<String> pkgList = null;
9289 synchronized (mPackages) {
9290 PackageParser.Package pkg = mPackages.get(mp.packageName);
9291 if (pkg == null) {
9292 Slog.w(TAG, " Package " + mp.packageName
9293 + " doesn't exist. Aborting move");
9294 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9295 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
9296 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
9297 + mp.srcArgs.getCodePath() + " to "
9298 + pkg.applicationInfo.sourceDir
9299 + " Aborting move and returning error");
9300 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
9301 } else {
9302 uidArr = new int[] {
9303 pkg.applicationInfo.uid
9304 };
9305 pkgList = new ArrayList<String>();
9306 pkgList.add(mp.packageName);
9307 }
9308 }
9309 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
9310 // Send resources unavailable broadcast
9311 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
9312 // Update package code and resource paths
9313 synchronized (mInstallLock) {
9314 synchronized (mPackages) {
9315 PackageParser.Package pkg = mPackages.get(mp.packageName);
9316 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -07009317 if (pkg == null) {
9318 Slog.w(TAG, " Package " + mp.packageName
9319 + " doesn't exist. Aborting move");
9320 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -07009321 } else if (!mp.srcArgs.getCodePath().equals(
9322 pkg.applicationInfo.sourceDir)) {
9323 Slog.w(TAG, "Package " + mp.packageName
9324 + " code path changed from " + mp.srcArgs.getCodePath()
9325 + " to " + pkg.applicationInfo.sourceDir
9326 + " Aborting move and returning error");
9327 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
9328 } else {
9329 final String oldCodePath = pkg.mPath;
9330 final String newCodePath = mp.targetArgs.getCodePath();
9331 final String newResPath = mp.targetArgs.getResourcePath();
9332 final String newNativePath = mp.targetArgs
9333 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -07009334
Kenny Rootbf023582012-05-02 16:56:15 -07009335 try {
9336 final File newNativeDir = new File(newNativePath);
9337
9338 final String libParentDir = newNativeDir.getParentFile()
9339 .getCanonicalPath();
9340 if (newNativeDir.getParentFile().getCanonicalPath()
9341 .equals(pkg.applicationInfo.dataDir)) {
9342 if (mInstaller
9343 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
9344 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9345 } else {
9346 NativeLibraryHelper.copyNativeBinariesIfNeededLI(
9347 new File(newCodePath), newNativeDir);
9348 }
Kenny Root6a6b0072010-10-07 16:46:10 -07009349 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07009350 if (mInstaller.linkNativeLibraryDirectory(
9351 pkg.applicationInfo.dataDir, newNativePath) < 0) {
9352 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9353 }
Kenny Root6a6b0072010-10-07 16:46:10 -07009354 }
Kenny Rootbf023582012-05-02 16:56:15 -07009355 } catch (IOException e) {
9356 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Root6a6b0072010-10-07 16:46:10 -07009357 }
9358
Kenny Rootbf023582012-05-02 16:56:15 -07009359
Kenny Root6a6b0072010-10-07 16:46:10 -07009360 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
9361 pkg.mPath = newCodePath;
9362 // Move dex files around
9363 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
9364 // Moving of dex files failed. Set
9365 // error code and abort move.
9366 pkg.mPath = pkg.mScanPath;
9367 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9368 }
9369 }
9370
9371 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -07009372 pkg.mScanPath = newCodePath;
9373 pkg.applicationInfo.sourceDir = newCodePath;
9374 pkg.applicationInfo.publicSourceDir = newResPath;
9375 pkg.applicationInfo.nativeLibraryDir = newNativePath;
9376 PackageSetting ps = (PackageSetting) pkg.mExtras;
9377 ps.codePath = new File(pkg.applicationInfo.sourceDir);
9378 ps.codePathString = ps.codePath.getPath();
9379 ps.resourcePath = new File(
9380 pkg.applicationInfo.publicSourceDir);
9381 ps.resourcePathString = ps.resourcePath.getPath();
9382 ps.nativeLibraryPathString = newNativePath;
9383 // Set the application info flag
9384 // correctly.
9385 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
9386 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
9387 } else {
9388 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
9389 }
9390 ps.setFlags(pkg.applicationInfo.flags);
9391 mAppDirs.remove(oldCodePath);
9392 mAppDirs.put(newCodePath, pkg);
9393 // Persist settings
9394 mSettings.writeLPr();
9395 }
9396 }
9397 }
9398 }
9399 // Send resources available broadcast
9400 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
9401 }
9402 }
9403 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
9404 // Clean up failed installation
9405 if (mp.targetArgs != null) {
Kenny Root6dceb882012-04-12 14:23:49 -07009406 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
9407 -1);
Kenny Root447106f2011-03-23 11:00:15 -07009408 }
9409 } else {
9410 // Force a gc to clear things up.
9411 Runtime.getRuntime().gc();
9412 // Delete older code
9413 synchronized (mInstallLock) {
9414 mp.srcArgs.doPostDeleteLI(true);
9415 }
9416 }
Kenny Rootdeb11262010-08-02 11:36:21 -07009417
Kenny Root447106f2011-03-23 11:00:15 -07009418 // Allow more operations on this file if we didn't fail because
9419 // an operation was already pending for this package.
9420 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
9421 synchronized (mPackages) {
9422 PackageParser.Package pkg = mPackages.get(mp.packageName);
9423 if (pkg != null) {
9424 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -07009425 }
9426 }
Kenny Root447106f2011-03-23 11:00:15 -07009427 }
Kenny Rootdeb11262010-08-02 11:36:21 -07009428
Kenny Root447106f2011-03-23 11:00:15 -07009429 IPackageMoveObserver observer = mp.observer;
9430 if (observer != null) {
9431 try {
9432 observer.packageMoved(mp.packageName, returnCode);
9433 } catch (RemoteException e) {
9434 Log.i(TAG, "Observer no longer exists.");
9435 }
9436 }
9437 }
9438 });
9439 }
9440
9441 public boolean setInstallLocation(int loc) {
9442 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
9443 null);
9444 if (getInstallLocation() == loc) {
9445 return true;
9446 }
9447 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
9448 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
9449 android.provider.Settings.System.putInt(mContext.getContentResolver(),
9450 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
9451 return true;
9452 }
9453 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009454 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -07009455
Kenny Root447106f2011-03-23 11:00:15 -07009456 public int getInstallLocation() {
9457 return android.provider.Settings.System.getInt(mContext.getContentResolver(),
9458 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION,
9459 PackageHelper.APP_INSTALL_AUTO);
9460 }
Amith Yamasani0b285492011-04-14 17:35:23 -07009461
9462 public UserInfo createUser(String name, int flags) {
Kenny Root461ff1f2011-08-09 09:43:03 -07009463 // TODO(kroot): Add a real permission for creating users
9464 enforceSystemOrRoot("Only the system can create users");
9465
Amith Yamasani13593602012-03-22 16:16:17 -07009466 UserInfo userInfo = sUserManager.createUser(name, flags);
9467 if (userInfo != null) {
9468 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
9469 addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
9470 mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
9471 }
Amith Yamasani0b285492011-04-14 17:35:23 -07009472 return userInfo;
9473 }
9474
9475 public boolean removeUser(int userId) {
Kenny Root461ff1f2011-08-09 09:43:03 -07009476 // TODO(kroot): Add a real permission for removing users
9477 enforceSystemOrRoot("Only the system can remove users");
9478
Amith Yamasani13593602012-03-22 16:16:17 -07009479 if (userId == 0 || !sUserManager.exists(userId)) {
Amith Yamasani0b285492011-04-14 17:35:23 -07009480 return false;
9481 }
Amith Yamasani13593602012-03-22 16:16:17 -07009482
9483 cleanUpUser(userId);
9484
9485 if (sUserManager.removeUser(userId)) {
9486 // Let other services shutdown any activity
9487 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
9488 addedIntent.putExtra(Intent.EXTRA_USERID, userId);
9489 mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
9490 }
9491 sUserManager.removePackageFolders(userId);
Amith Yamasani0b285492011-04-14 17:35:23 -07009492 return true;
9493 }
Kenny Root0aaa0d92011-09-12 16:42:55 -07009494
Amith Yamasani13593602012-03-22 16:16:17 -07009495 private void cleanUpUser(int userId) {
9496 // Disable all the packages for the user first
9497 synchronized (mPackages) {
9498 Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
9499 for (Entry<String, PackageSetting> entry : entries) {
9500 entry.getValue().removeUser(userId);
9501 }
9502 if (mDirtyUsers.remove(userId));
9503 mSettings.removeUserLPr(userId);
9504 }
9505 }
9506
Kenny Root0aaa0d92011-09-12 16:42:55 -07009507 @Override
9508 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
9509 mContext.enforceCallingOrSelfPermission(
9510 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
9511 "Only package verification agents can read the verifier device identity");
9512
9513 synchronized (mPackages) {
9514 return mSettings.getVerifierDeviceIdentityLPw();
9515 }
9516 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009517
Amith Yamasani13593602012-03-22 16:16:17 -07009518 @Override
Amith Yamasani742a6712011-05-04 14:49:28 -07009519 public List<UserInfo> getUsers() {
Amith Yamasani13593602012-03-22 16:16:17 -07009520 enforceSystemOrRoot("Only the system can query users");
9521 return sUserManager.getUsers();
9522 }
9523
9524 @Override
9525 public UserInfo getUser(int userId) {
Amith Yamasani5bb87cd2012-06-14 11:32:13 -07009526 enforceSystemOrRoot("Only the system can query user");
Amith Yamasani13593602012-03-22 16:16:17 -07009527 return sUserManager.getUser(userId);
9528 }
9529
9530 @Override
Amith Yamasanib8151ec2012-04-18 18:02:48 -07009531 public void setUserName(int userId, String name) {
Amith Yamasani13593602012-03-22 16:16:17 -07009532 enforceSystemOrRoot("Only the system can rename users");
Amith Yamasanib8151ec2012-04-18 18:02:48 -07009533 sUserManager.setUserName(userId, name);
9534 }
9535
9536 @Override
9537 public ParcelFileDescriptor setUserIcon(int userId) {
9538 enforceSystemOrRoot("Only the system can update users");
9539 return sUserManager.setUserIcon(userId);
Amith Yamasani742a6712011-05-04 14:49:28 -07009540 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009541
9542 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009543 public void setPermissionEnforced(String permission, boolean enforced) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009544 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
9545 if (READ_EXTERNAL_STORAGE.equals(permission)) {
9546 synchronized (mPackages) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -07009547 if (mSettings.mReadExternalStorageEnforced == null
9548 || mSettings.mReadExternalStorageEnforced != enforced) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009549 mSettings.mReadExternalStorageEnforced = enforced;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009550 mSettings.writeLPr();
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07009551
9552 // kill any non-foreground processes so we restart them and
9553 // grant/revoke the GID.
9554 final IActivityManager am = ActivityManagerNative.getDefault();
9555 if (am != null) {
9556 final long token = Binder.clearCallingIdentity();
9557 try {
9558 am.killProcessesBelowForeground("setPermissionEnforcement");
9559 } catch (RemoteException e) {
9560 } finally {
9561 Binder.restoreCallingIdentity(token);
9562 }
9563 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009564 }
9565 }
9566 } else {
9567 throw new IllegalArgumentException("No selective enforcement for " + permission);
9568 }
9569 }
9570
9571 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009572 public boolean isPermissionEnforced(String permission) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009573 synchronized (mPackages) {
9574 return isPermissionEnforcedLocked(permission);
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009575 }
9576 }
9577
9578 private boolean isPermissionEnforcedLocked(String permission) {
9579 if (READ_EXTERNAL_STORAGE.equals(permission)) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -07009580 if (mSettings.mReadExternalStorageEnforced != null) {
9581 return mSettings.mReadExternalStorageEnforced;
9582 } else {
9583 // if user hasn't defined, fall back to secure default
9584 return Secure.getInt(mContext.getContentResolver(),
9585 Secure.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0) != 0;
9586 }
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009587 } else {
9588 return true;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009589 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009590 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -07009591
9592 public boolean isStorageLow() {
9593 final long token = Binder.clearCallingIdentity();
9594 try {
9595 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
9596 .getService(DeviceStorageMonitorService.SERVICE);
9597 return dsm.isMemoryLow();
9598 } finally {
9599 Binder.restoreCallingIdentity(token);
9600 }
9601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602}